2010-03-25 118 views
9

以我的C++程序,我需要调用该C API:如何传递一个C++成员函数的C API作为参数

GConn* gnet_conn_new (const gchar *hostname, 
         gint port, 
         GConnFunc func); 

其中GConnFunc定义为:

void (*GConnFunc) (GConn *conn); 

我的问题是,如果我有一个C++类,并有一个成员函数,如:

Class A { 
public: 
    A(); 
    void my_func (GConn* conn); 
} 

在我A::A()构造函数,我怎么能传递this->myfuncgnet_conn_new作为GConnFunc参数?

谢谢。

+0

建议的重复(http://stackoverflow.com/questions/130322/how-do-you-pass-a-member-function-pointer)不*看起来是重复的。它讨论了在所有C++上下文中传递指向成员的指针。 – dmckee 2010-03-25 17:30:18

回答

11

大多数API提供一个指针大小的“用户数据”的说法,这应该是这样的:

GConn* gnet_conn_new (const gchar *hostname, 
        gint port, 
        GConnFunc func, 
        void* user_data); 

这将允许你在USER_DATA直传一个实例,有你的C函数的成员函数像这样:

void my_func(GConn *conn, void* user_data) 
{ 
    ((MyClass*)user_data)->MyMemberFunc(conn); 
} 

也许你的API有一个替代或类似的'用户数据'参数的地方。否则,如果没有全局或静态,你无法真正做到这一点。

3

你要么需要一个包装函数来处理这个问题,要么你可以使my_func静态(假设它不需要访问任何实例变量)。

2

C++类中的非静态成员函数有一个隐藏的“this”参数。如果你可以假设它转换为C,则该函数将转变为:

void A_my_func (A * const this, GConn* conn); 

有没有真正的方式自动执行代码中的这种转换,虽然你可以使用上面的原型编写一个包装函数,并传递一个指向它的C函数。

通常的处理方法是传递一个空闲(非成员)函数或一个类静态函数。这两种类型都没有隐藏参数。

2

简短的回答,你不能。

龙答:

只要有足够的回旋余地的,你需要给你打电话可以拼凑,您只需注册并呼吁作为中介功能的API。通常,回调函数允许您包含传递给该函数的额外数据以及由回调对象生成的信息。它通常被称为“client_data”,类型为void *或long。在这种情况下,您可以简单地使用这些数据来包含足够的信息来调用所需实例的功能,例如在boost :: function <>中进行抛出。

请注意,这个委托给您的成员函数的中介函数可以是静态成员或自由函数。

不幸的是,您在这里没有这个选项,所以您的工作将变得更加艰难。您确实需要一些方法来确保正确的实例被赋予了消息,并且您无法从回调的数据中识别该实例。有可能会或可能不会为你工作了几个选项:

  1. 确保今后不再使用一个以上的实例作为回调目标。用一个单例或全局类型注册该实例,该类型跟踪引用此类型事件的一个时间实例。

  2. 注册尽可能多的实例,只要确保他们都收到消息,然后处理或不处理。您可以在这里使用一种“责任链”,目标有机会处理事件,然后返回让循环知道应该继续还是停止的事情。

总之,没有直接的方法来做你想做的事情,但是如果你考虑选项,可能会有答案获得你需要的东西。用作提供给C API函数的回调函数的任何函数都必须作为函数指针参考,而不是任何类型的成员指针......并且不幸也不是函子。 C不知道如何处理这些事情,所以你的回调必须是一个自由函数或静态成员。

相关问题