Atmocreations
Atmocreations

Reputation: 10071

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 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

Upvotes: 7

Views: 18534

Answers (6)

Luna
Luna

Reputation: 21

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);
}

Upvotes: 1

rldrenth
rldrenth

Reputation: 35

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);

Upvotes: -1

ruslik
ruslik

Reputation: 14900

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.

Upvotes: 5

lj_enjoylife
lj_enjoylife

Reputation: 19

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;
}

Upvotes: -1

Sridhar Iyer
Sridhar Iyer

Reputation: 2840

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.

Upvotes: 0

Jonathan Grynspan
Jonathan Grynspan

Reputation: 43472

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.

Upvotes: 8

Related Questions