2017-05-12 41 views
0

我想在C++中做C包装。C++类成员函数C结构函数指针

但我不能将类内的函数转换为结构函数指针。

不应将myCallback函数用作静态函数,因为它必须被覆盖。

下面是示例代码:

#include <iostream> 

extern "C" { 
typedef struct _client_config 
{ 
    void (*on_connect)(void *client, int result); 
} client_config; 
} 

class Parent 
{ 
public: 
    Parent() {}; 
    ~Parent() {}; 

    virtual void myCallback(void* hello, int world) = 0; 
}; 

class Child : public Parent 
{ 
public: 
    Child() {}; 
    ~Child() {}; 

    void myCallback(void* hello, int world) 
    { 
     printf("Hello World! \n"); 
    } 
}; 

int main(void) 
{ 
    Parent* myClass = new Child(); 

    client_config* myClientConfig = (client_config *)malloc(sizeof(client_config)); 

    myClientConfig->on_connect = myClass->myCallback; 

    return 0; 
} 

这是在编译过程中,编译器说的话:

Error 1 error C3867: 'Parent::myCallback': function call missing argument list; use '&Parent::myCallback' to create a pointer to member 
Error 2 error C2440: '=' : cannot convert from 'void (__thiscall Parent::*)(void *,int)' to 'void (__cdecl *)(void *,int)' 

任何人都可以指出绑定一个类的成员函数的结构函数指针的方式或我在这里做错了什么?

回答

0

C函数库的函数指针仅与extern "C"自由函数兼容。 (即使静态成员函数不兼容,语言链接也是错误的)。

你将不得不使用蹦床等函数,询问你接收到一个指向你的对象的指针的对象(该库提供了一种方法来存储某种形式的用户数据,这些数据可以是在回调中检索,不是吗?或许client参数是这样的,你必须阅读文档。),投到Parent*,并执行成员调用。编译器不会为你做这件事。

extern "C" void connect_trampoline(void* client, int result) 
{ 
    Parent* my_object = static_cast<Parent*>(client); 
    my_object->myCallback(result); 
} 

myClientConfig->on_connect = &connect_trampoline; 

C++库通常是由接受std::function它可以携带其自身的状态编码以使这更容易,例如。但是,在C库使用的C编程风格中,你必须先找到你的对象,然后在使用成员之前做一个丑陋的表演。

万一库做出某种形式的控制,以回调访问下的指针,但确实传递一个指针在回调关联的库对象,你可以使用全局std::map<library_object*, Parent*>查找你的对象。这种方法也避免了演员阵容。


要小心,当你手中的指针到对象到图书馆抱你,你给它完全相同的类型(Parent*在这种情况下),你将在稍后投退。如果你给Derived*,效果是做reinterpret_cast<Parent*>(p_derived)这是非常糟糕的。 (static_castvoid*当指针指向库时,static_castParent*当您收回时,并且C++标准说这个序列与reinterpret_cast)的行为完全相同)