开发者

Cast pointer to member function to normal pointer

Currently I have a class of this kind, shortened for simplicity:

class MyClass {
    public: 
        MyClass();
        void* someFunc(void* param);
}

Now I need to call a function of this kind (not member of any class and which 开发者_C百科I unfortunately cannot change) but which I need to call anyway:

void secondFunc(int a, int b, void *(*pCallback)(void*));

Now I need to pass the address of someFunc of an instance.

A not working sample:

MyClass demoInstance;
// some other calls
secondFunc( 1, 2, demoInstance::someFunc() );

I've tried also with casts like:

(void* (*)(void*)) demoInstance::someFunc;
reinterpret_cast<(void* (*)(void*))>(demoInstance::someFunc);

How can I call this function with a class' member function as parameter so that this one can use it as callback?

Any idea or remark is appreciated. Thanks and regards tobias


You can't call the member function directly. Member function pointers are not the same type as function pointers.

You'll need to wrap it in a compatible function somehow. However, if your outer function (the one taking the function pointer as an argument) is not re-entrant and does not supply an extra argument for use by the function pointer, you won't be able to pass the instance upon which the member function operates, so you won't actually be able to make the call.


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.


There is a round about way of doing it. Since C++ names are mangled you can't directly use it for non-static functions.. however since non-static functions have the same signatures as C functions, you can directly use them as callbacks. So for non-static functions, you can have static function wrappers. This page explains this approach in detail.


class MyClass 
{
public: 
    MyClass();
    void* someFunc(void* param);
};

void* callback(void*)
{
    MyClass instance;
    instance.someFunc(0 /* or whatever */);
}

void foo()
{
    secondFunc( 1, 2, callback);
}


See this sample:

#include <iostream>

class MyClass 
{
public: 
    MyClass()
    {
    }

    void* someFunc(void* param)
    {
        std::cout << "someFunc" << std::endl;
        return (void*)0;
    }
};

typedef void* (MyClass::*MemFun)(void*);

void secondFunc(int a, int b, MemFun fn)
{
    MyClass* ptr = 0;
    // This is dangerous! If the function someFunc do not operate the data in the class.
    // You can do this.
    (ptr->*fn)(0);
    std::cout << "Call me successfully!" << std::endl;
}

int main()
{
    secondFunc(1, 2, &MyClass::someFunc);

    system("pause");

    return 0;
}


Didn't see the part about not being able to change the second function before.

Define a structure with pointers to the member function and to the object:

struct MyData {
   MyStruct  *myInstance;
   (void *)(MyStruct::myFunction)(void *data);
   void * dataPointer ;
}

Create a function that can invoke the proper method:

void *proxyFunc( MyData *data)
{
  return (data->myInstance->*(data->myFunction))(data->dataPointer);
}

Then call the function 2 as:

MyData  dataP = { someInstance, &MyStruct::someFunc, &dataPtr };
secondFunc(proxyFunc, &dataP);


use union can be easy

#include <iostream>

using namespace std;

class Data {
public:
    Data(const int data) : num(data) {

    }

    void printData() const {
        printf("%d", this->num);
    }

private:
    int num;
};

union Test {
    decltype(&Data::printData) member_fun;

    void (* normal_function)(...);
};

int main() {
    Test t;
    t.member_fun = &Data::printData;
    Data data(10);
    (*t.normal_function)(&data);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜