Question

The question: Is there a way to cast pointer to member function to intptr_t in C++?

Known factors:

  1. I know member function pointer is very special one
  2. I know that member function passes hidden "this" parameter (__thiscall).
  3. I know that sizeof(member function pointer) > sizeof(intptr_t) in some cases, in this question I'm only talking about the case where it is possible, i.e. in my case sizeof(member function pointer) == sizeof(intptr_t).
  4. And finally I know that casting pointers to intptr_t isn't a good pattern.

Sample code:

class test // No inheritance, in the case I need
    {
    public:
    void func();    // No virtual, or any special modifiers in the case I need
    };

void main2()
    {
    intptr_t p = &test::func;
    };

I know a workaround to do this cast, but I don't like it, since it requeres a temp variable:

void my_way()
    {
    intptr_t p;
    auto t = &test::func;       // Temp variable, I don't like the fact I need to use it, but I have no other way for now
    p = *reinterpret_cast<intptr_t*>(&t);
    };

So the question is how to do the trick inline as an rvalue expression, with no temp variable (and no memcpy which is the same).

Example:

reinterpret_cast<??>(???_cast<??>(???_cast<??>( &test::func )))

(I don't care about how beautiful the expression will be).

-------------------------( below some thoughts about why, not the question )--------------------------------

There are some simmilar themes on this site, but all of them mostly speaking about "why you do so?", or "why do you need this?", and speaking about this solves the problem for the one who askes, but not for me.

Why do I need this staff: I'm writing some kind of task where I've decided to implement my own mechanism for dynamic linking. There can be several specific applications.

In my case - dynamic linkage mechanism - I want to pass a pointer to function to another module. I have a class and an interface as a separate structure (I know, there are libs with the same approach). All the classes using this mechanism are known to be plain (no inheritance at all, so no virtuals and etc). All this runs on x86 32 bit, or at most on 64 Windows, compiled by MSVC 2012. As interface is completely isolated from class it uses an array of pointers. Lib passes the array to the host process. And in the host process I have this... It's not even a "problem", but still:

inline int my_interface::func_name(int param)
    {
    decltype(&interface_name::func_name) temp;
    *((intptr_t*)&temp) = reinterpret_cast<interface_name::funcs*>(interface_desc->funcs)->func_name;
    return (reinterpret_cast<decltype(this)>(object)->*temp)(param);
    };

It's an inline function, so I want it to be as small as possible, and if it is possible I'd like to eliminate "temp", because I'm not sure if the compiler will correctly eliminate this, even with all optimizations.

Other applications (hypotetic): - What if i want to protect the memory page where my member function resides with a specific guard. WinAPI gives me a way to do so, but it needs address of the page. There is no problem to do this for normal function, but for member - only with WA I described? Or there is a way? - What if I want to patch the image in runtime? I.e. to find some const and replace it with another? There can be at least several reasons for runtime patching: 2.1 dynamic linkage relocation process, 2.2 code obfuscation.

This is just for a note - readers often ask "what for", I don't want to discuss why, because in my opinion there can be many applications, all of them not for newbie, but more for security guys etc...

I herebly ask not to discuss "Why do so?", "Why don't use existing mechanism for dll/boost/other libs/other languages?" in this thread.

Was it helpful?

Solution

No, the spec does not allow you to cast function pointers or member pointers to intptr_t. The reason for this is because you may need more than one intptr_t's worth of data to describe them. For example, member pointers on gcc are 3 intptr_t's long, and MSCVs range from 1 to 4 intptr_t's long. Much of this is used to handle virtual functions.

On some old hardware (that C++ supports), pointers are also actually smaller than function pointers. This happens on small systems where you may only need to point to an 8-bit memory structure, but programs get loaded into a 16-bit program memory space.

Much of the time, this pattern you are trying to use is used to create delegates: member function pointers permanently tied to a specific object. This can be done with 2 int pointers and a wrapping function

struct Delegate
{
    intptr_t   obj;  // I'll use intptr_t here, but often this is void*
    intptr_t   func;
};

// you need one of these for each type of mfp you use
static void callT_Test(intptr_t obj)
{
    T* realObj = reinterpret_cast<T*>(obj);
    realObj->test();
}

// constructing a delegate to call test on t
Delegate d;
d.obj = reinterpret_cast<intptr_t>(&t);
d.func = &callT_Test;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top