将参数中的静态函数指针替换为实例中方法的指针
Replacing static function pointer in argument by a pointer to a method in instance
我使用第三方库,该库要求将指向静态函数的指针作为回调参数传递。现在我必须做这样的事情:
static int MyCallback( ...)
{
// Callback code here...
}
int main( int argc, char* argv[])
{
ThirdPartyFunction( &MyCallback, ... );
}
我想做的是用C++类实例的成员方法替换我必须提供的静态回调函数。类似这样的东西:
class MyClass
{
public:
int MyCallbackMethod( ... );
};
int main(int argc, char* argv[])
{
MyClass instanceOfMyClass;
ThirdPartyFunction( &(????), ... );
}
我的问题是,当我将&instanceOfMyClass::MyCallbackMethod
传递给ThirdPartyFunction()
时,它不会编译。当启动一个线程(比如,std::thread)时,会传递(&MyClass::MyCallbackMethod, this)
,但在这种情况下,ThirdPartyFunction
(似乎是用C而不是C++编写的)不允许我传递函数指针和拥有该方法的对象。
另一方面,如果我在MyClass
中声明static int MyCallbackMethod
,它当然有效,但我没有实例,这不是我想要的。
我的问题很简单:是否可以传递类似(&MyClass::MyCallbackMethod, this)
(实例方法)的东西来代替&MyClass::MyCallbackMethod
(static方法++11。
提前感谢您的帮助!
编辑1
我使用libmicrohttpd(请参阅microhttpd.h)
功能"ThirdPartyFunction
":
_MHD_EXTERN struct MHD_Daemon *
MHD_start_daemon_va (unsigned int flags,
uint16_t port,
MHD_AcceptPolicyCallback apc, void *apc_cls,
MHD_AccessHandlerCallback dh, void *dh_cls,
va_list ap);
例如,MHD_AcessHandlerCallback
被声明为:
typedef int
(*MHD_AccessHandlerCallback) (void *cls,
struct MHD_Connection *connection,
const char *url,
const char *method,
const char *version,
const char *upload_data,
size_t *upload_data_size,
void **con_cls);
所以我必须使用一个有这个签名的函数。我想在实例方法而不是静态函数上使用相同的签名。
如果ThirdPartyFunction
是在C中定义的,那么它不可能以这样的方式声明,即您可以将非静态成员函数传递给它。
只能将正则函数绑定到正则函数指针。因此,编写一个包装函数,它不是调用该成员函数的非静态成员。但是如何获得一个实例来调用非静态成员呢?
C Api可能允许您传递指向将传递给回调的任意数据的void*
。如果是,则可以将对象实例作为任意数据传递。
如果没有,那么您可以使用静态实例或指向实例的静态指针,但这些可能会很有问题,因为这会使回调在静态初始化期间不可用,并且使其不可重入,这也会使其在多线程上下文中不可用。
根据您的编辑更新:
您的API确实支持将void*
数据传递给回调(两个回调),因此我建议您使用它。
* @param apc callback ...
* @param apc_cls extra argument to apc
不能传递指向成员函数的指针来代替指向非成员或静态成员函数的指示器,因为成员函数需要调用它们的对象。指向该对象的指针将成为成员函数的隐式this
参数。
如果需要将调用分派给成员函数,则需要有一种方法来查找调用该函数的对象。这里有两种通用方法:
- 将指向对象的对象指针放在程序已知的某个位置。传递一个静态函数来查找对象目标,并对其调用回调
- 依赖API功能,该功能允许您将"用户数据"传递到回调,并在回调中放置对象指针
在这两种情况下,都将静态或非成员函数注册为第三方API的回调函数。
以下是第一种方法的示例:
struct MyClass {
int MyCallbackMethod( ... );
};
static MyClass *instancePointer;
static int MyStaticCallback( ...) {
instancePointer->MyCallbackMethod(...);
}
int main(int argc, char* argv[]) {
MyClass instanceOfMyClass;
// Point instancePointer to instanceOfMyClass for the static callbacl
instancePointer = &instanceOfMyClass;
// Register static callback
ThirdPartyFunction( &MyStaticCallback, ... );
}
第二种方法取决于API。假设您的回调收到一个void*
,您可以将其传递给ThirdPartyFunction
,实现如下:
struct MyClass {
int MyCallbackMethod( ... );
};
static int MyStaticCallback(void* userData) {
MyClass *instancePointer = (MyClass*)userData;
instancePointer->MyCallbackMethod();
}
int main(int argc, char* argv[]) {
MyClass instanceOfMyClass;
ThirdPartyFunction( &MyStaticCallback, (void*)(&instanceOfMyClass));
}
在您的情况下,看起来cls
指针是传递回回调的指针,apc_cls
/dh_cls
是您传递给第三方函数进行注册的指针。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 对于C++中使用智能指针的指针算术限制,有没有一种变通方法
- 有没有一种"cleaner"的方法可以在指向基的指针向量中找到派生类的第一个实例?
- 在c++中为我自己的基于指针的数组分配内存的正确方法
- 将成员函数指针作为参数传递给模板方法
- 通过函数指针定义类范围之外的方法
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- 如何访问由共享指针保存的类方法?
- 初始化指向类实例的智能指针并访问其方法
- 我无法使用C++指针指向类方法返回的 std::vector
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 有没有将变量名称转换为双指针的简短方法?
- 在自定义 std::vector-like 容器中处理指针和非指针模板类型的最佳方法是什么?
- 如何在成为指向基类的指针后保留对子类方法的使用?
- 从纯虚拟类 (A) 派生的指针无法访问来自纯类 (B) 的重载方法
- 类指针方法崩溃程序
- 证明两指针方法有效(对和)
- Qt 删除指针方法
- 我如何将一些类的指针方法转换为指针函数