Cast pointer to member function to normal pointer

前端 未结 6 596
抹茶落季
抹茶落季 2020-11-28 15:52

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

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


        
相关标签:
6条回答
  • 2020-11-28 16:25

    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.

    0 讨论(0)
  • 2020-11-28 16:28

    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);
    
    0 讨论(0)
  • 2020-11-28 16:30
    class MyClass 
    {
    public: 
        MyClass();
        void* someFunc(void* param);
    };
    
    void* callback(void*)
    {
        MyClass instance;
        instance.someFunc(0 /* or whatever */);
    }
    
    void foo()
    {
        secondFunc( 1, 2, callback);
    }
    
    0 讨论(0)
  • 2020-11-28 16:35

    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.

    0 讨论(0)
  • 2020-11-28 16:36

    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;
    }
    
    0 讨论(0)
  • 2020-11-28 16:49

    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.

    0 讨论(0)
提交回复
热议问题