Cast Pointer to Member Function to Normal Pointer

Cast pointer to member function to normal pointer

The difference between a C function and a C++ member function is that C function uses cdecl calling convention, while member functions uses thiscall calling convention (and you can't even take their address!).

As I understand, you actually want that secondFunc() to call the member function of a particular instance of class (let's call it this). Well, addresses of member functions of all the instances of a particular class are the same. In order to pass the pointer to the object, you will need a side channel. In this case it could be static variable. Or, if you want MT support, you'll have to use Thread Local Storage (TLS),

This requires one callback per SomeFunc-type member, but you would need a dispatcher somewhere anyway.

C++ class member function pointer to function pointer

No. A member function is not a free function. The type is entirely different, and a pointer to a member function (PTMF) is a completely different, incompatible object from a function pointer. (A PTMF is usually much bigger, for example.) Most importantly a pointer-to-member must always be used together with an instance pointer to the object whose member you want to call, so you cannot even use a PTMF the same way you use a function pointer.

The easiest solution for interacting with C code is to write a global wrapper function that dispatches your call, or to make your member function static (in which case it becomes essentially a free function):

// global!

Engine * myEngine;
int theCallback(lua_State * L)
{
return myEngine->pcall_log(L);
}

Engine::Run()
{
/* ... */
myEngine = this;
luabind::set_pcall_callback(&theCallback);
/* ... */
}

The conceptual problem here is that you have an engine class, although you will practically only have one single instance of it. For a genuine class with many objects, a PTMF wouldn't make sense because you'd have to specify which object to use for the call, whereas your engine class perhaps is essentially a singleton class which could be entirely static (i.e. a glorified namespace).

cast a pointer to member function in derived class to a pointer to abstract member function

You could shorten this example a lot:

struct B {
virtual void foo() = 0;
};

struct D : B {
void foo() override { }
};

int main() {
void (B::*ptr)() = &D::foo; // error: cannot initialize a variable of
// type 'void (B::*)()' with an rvalue of type
// 'void (D::*)()': different classes ('B' vs 'D')
}

The error message, at least on clang, is pretty clear. gcc just says cannot initialize. The issue is just that you cannot implicitly convert a pointer-to-derived-member to a pointer-to-base-member. But you can do it explicitly with static_cast:

void (B::*ptr)() = 
static_cast<void (B::*)()>(&D::foo); // ok!

Side-note: please remove the CALL_MBR_FUNC macro from your code and never write such a thing ever again.

Cast pointer to member function to intptr_t

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;


Related Topics



Leave a reply



Submit