简体   繁体   中英

C++ static member function as C callback needs to access non static reference

In my C++ code I have a dependecy on a C library. This C library lets me define a callback with 3 arguments. Example:

file.c:

#ifdef __cplusplus
extern "C"{
#endif
     typedef void(*callback)(argument* 1, argument* 2, argument* 3);
...
     void set_callback(ARG1, callback name_of_callback);
...

In the C++ library i'm developing i want this callback to be a member function of a class, since I cannot pass directly a member function as the callback to the C library I created a static function to be the callback and inside this static function I want to have a reference to a class object and call its member function to do the work.

Now my problem is that my static functions needs to have the 3 arguments specified by the C library, so i'm not finding a way of having a reference to an object of the class i'm developing inside that static function. Example of I wanted to do:

MyClass.h:

class MyClass:
public:
   MyClass();
   void my_function(argument*1, argument* 2, argument* 3);
   static void my_callback(argument* 1, argument* 2, argument*3);

MyClass.cpp:

MyClass::MyClass(){
    set_callback(ARG1, my_callback);
}

void MyClass::my_function(argument*1, argument* 2, argument* 3){ 
      /* Do something */}
void MyClass::my_callback(argument* 1, argument* 2, argument*3){
    Object->my_function(1, 2, 3);
}

The reason to not set the class members as static is that i want to be able to create and destroy objects of this class for testing purposes and control the state of the object within the tests.

I'm using g++ and gcc, hope someone can give some help with this. Thanks in advance.

You can create a static member function or a pure 'C' function to do this, consider my example below:

/**
 * C++ part
 */
class obj
{
public:
    obj() {}
    ~obj() {}

    void doSomething(int a, int b) { cout << "result = " << a+b << endl; }
};

/**
 * C Part
 */
#ifdef __cplusplus
extern "C"
#endif
{
typedef void (*callback)(void* one, void* two, void* three);

callback g_ptr = NULL;
void* arg = NULL;

void c_lib_core (void)
{
    printf ("C Lib core...\n");
    if (g_ptr)
    {
        g_ptr(arg, NULL, NULL);
    }
}

void set_callback (void* arg, callback ptr)
{
    g_ptr = ptr;
}

void my_callback (void* one, void* two, void* three)
{
    obj* my_obj = (obj*) one;

    my_obj->doSomething(1,2);
}

#ifdef __cplusplus
}
#endif



int main (void)
{
    obj a;

    set_callback (&a, my_callback);

    c_lib_core ();
}

Output:

C Lib core...
result = 3

I pass a pointer to the C++ object as argument 1. This allows the callback to cast it back to C++ and call it. The c_lib_core stuff is just so I can simulate the callback of the callback function for testing purposes. This, along with the global variables will be in the C code somewhere. You only need to implement a single C function and set ARG1 to your object and you are good to go.

Assuming no concurrency concerns, which i don't know if it's the case, the simpler solution could be to define an static instance and use that in your static function.

Something like this.

MyClass.h

class Object;

class MyClass
{
public:
    MyClass();
    static Object* object;
    static void callback();
    ~MyClass();

};

MyClass.cpp

Object* MyClass::object;

MyClass::MyClass()
{
    object = new Object();
}

void MyClass::callback() {
    object->sayHello();
}

MyClass::~MyClass()
{
    delete object;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM