0

In C for example I can get function address by

uint64_t ptr = (uint64_t)&MyFunction;

But In C++ I'm getting error "invalid type conversion" for following

uint64_t ptr = (uint64_t)&MyClass::MyFunction;

How do I get address for C++ non-static function?

Any help would be greatly appreciated

Edit:
I need to get this address please see this image

class MyClass
{
public:
    void MyFunction()
    {
    
    }
};

void MyFunction()
{

}

int main()
{
    uintptr_t ptr1 = (uintptr_t)&MyFunction;
    uintptr_t ptr2 = (uintptr_t)&MyClass::MyFunction; // invalid type conversion

    return 0;
}
Aplet123
  • 33,825
  • 1
  • 29
  • 55
malidu
  • 41
  • 1
  • 5
  • 1
    You can not. Address of a non-static members can not be converted to `uintptr_t`. – SergeyA Jul 20 '21 at 22:00
  • 1
    You should show an example demonstrating exactly what you are trying to accomplish. Numerous options exist but their suitability depends on your intended purpose. – paddy Jul 20 '21 at 22:09
  • @PeteBecker Wrong. A pointer to function is a pointer. (Pointers to members however, are not pointers) – eerorika Jul 20 '21 at 22:22
  • Whoops. That was supposed to be “a pointer-to-member-function is not a pointer”. – Pete Becker Jul 20 '21 at 23:13

4 Answers4

1

C++ Get address for non-static function

You can get "address" of a non-static member function using the addressof operator. The address that you get will be of type "pointer to member function" (which despite their name, are not pointers). You cannot convert that pointer to member function into an integer.


In C for example I can get function address by

uint64_t ptr = (uint64_t)&MyFunction;

You can achieve the same in C++ although not directly and not on all systems ("not on all systems" also applies to C; your C example won't work on all systems). And it can only be achieved for free functions or static member functions.

In C++, function pointers cannot be directly converted to integers. Only object pointers can be. Converting a function-pointer to pointer-to-void (which is an object pointer) is allowed if the language implementation supports it . As such, following would be valid on such supporting systems:

using Fun = decltype(MyFunction); // not a non-static member function
Fun* function_ptr = &MyFunction;
void* void_ptr = reinterpret_cast<void*>(function_ptr)
std::uintptr_t int_ptr = reinterpret_cast<std::uintptr_t>(void_ptr);

void* void_ptr_back = reinterpret_cast<void*>(int_ptr);
Fun* function_ptr_back = reinterpret_cast<Fun*>(void_ptr_back);
assert(function_ptr == function_ptr_back);

If the system doesn't support this conversion between function pointers and void*, then the program is safely ill-formed.

Note that this applies only to function pointers, and not to member function pointers. If MyClass::MyFunction is a non-static member function (edit: and it is in your edited question), then there is no standard way to convert it to an integer.

P.S. Reinterpreting an object pointer as std::uint64_t is guaranteed to work only on systems where the iteger can represent all pointer values. It may be so at the moment, but for future portability, using std::uintptr_t is recommended.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

A pointer to a member function, in general, does not fit in the same size as a plain pointer to function. It needs to encode virtual function ID and contains several fields besides the underlying member function address, depending on how complex the situation is (multiple inheritance, virtual base classes, etc.)

So, you can't cast it to just a pointer to a function. Even if you did, how would you call it? Unlike with a non-member function, you need to give it the hidden this parameter.

And the address of some specific member function might not even be useful; if it's a virtual function, then the actual function called depends on the type of the object it is called on. Thus, it needs to encode the virtual function ID.

Just look at the sizeof a pointer to a member function, compared to the sizeof a plain function or void*. Also, you might find compiler arguments that control whether a pointer-to-member is encoded in the simplest way possible for that class (which requires it to be a complete type) or always uses the most general form.

JDługosz
  • 5,592
  • 3
  • 24
  • 45
  • pointer sizes are same, 8 bytes on 64 CPU – malidu Jul 20 '21 at 22:58
  • Try again with a class that has virtual bases and virtual functions of that signature. https://godbolt.org/z/GY1faqz7f – JDługosz Jul 20 '21 at 23:10
  • Also see [Do all pointers have the same size in C++](https://stackoverflow.com/questions/71870205/do-all-pointers-have-the-same-size-in-c) – Jason Aug 07 '22 at 12:54
-1

I believe the problem you may be encountering is a scope problem or a size problem. Make sure the function's address you are looking for is in the proper scope. After determining this you can use simple pointers to locate function addresses in memory using a pointer. C++ relies on the underlying size of the machine's processor to determine address sizes. So do not use uint64_t to gather a pointer that might not fit that size.

Here is some simple code to print function addresses in C/C++:

#include<stdio.h>
  
void MyFunction()
{
    printf("This is My Function!");
}
  
int main(void)
{
    printf("Main address:%p\n", main);
    printf("MyFunction address : %p\n", funct);
    return 0;
}

Note: cout can be used for this as well.

I hope this helped! If not, leave a comment for further explanation or how it could be more helpful!

mroussell
  • 17
  • 1
  • 6
  • The problem in the question comes from `(uint64_t)&MyClass::MyFunction`. `&MyClass::MyFunction` is a pointer-to-member-function, not an ordinary pointer to function, so giving examples that use ordinary function pointers is (ahem) pointless. – Pete Becker Jul 20 '21 at 22:22
  • @PeteBecker Exactly, thus the pointer is out of the scope of being a function address pointer, which is in fact a pointer. The snippet you showed is in fact a pointer-to-member function, which is not a pointer. Thus the scope problem. – mroussell Jul 20 '21 at 22:43
  • The format specifier `%p` requires that the argument has type `void*`. That is not the type of the arguments that you pass. The behaviour of this example program is undefined. – eerorika Jul 20 '21 at 22:46
  • @mroussell — that’s not what “scope” means. – Pete Becker Jul 20 '21 at 23:11
-1

I was able to get the pointer

 auto _ptr = &MyClass::MyFunction;
 uintptr_t ptr = *((uintptr_t*)&_ptr);

Thanks for help

malidu
  • 41
  • 1
  • 5