我在外部库中有一个函数,我无法使用以下签名进行更改:
void registerResizeCallback(void (*)(int, int))
Run Code Online (Sandbox Code Playgroud)
我想传递一个成员函数作为回调,因为我的回调需要修改实例变量.
显然,这是不可能的简单:
registerResizeCallback(&Window::Resize);
Run Code Online (Sandbox Code Playgroud)
所以我不确定如何解决这个问题.
正如伊戈尔奥克斯所说,你不能这样做.这个问题的其余部分并不是对你的问题的答案,而是讨论这样的事情应该如何与正确设计的回调API一起使用(看起来你正在使用的那个不是).
大多数设计良好的回调接口允许您提供" void *"或其他方式来获取回调中的上下文.在C++中使用它的一种常用方法是在void *context参数中传递一个对象指针,然后回调函数可以将它强制转换为对象指针并调用成员方法来完成实际工作.你正在使用的回调API没有提供上下文数据太糟糕了.
严格来说,回调必须是extern "C",但使用静态成员方法进行回调很常见,我认为在实践中从来没有问题.(这假设回调API是C接口,这是迄今为止最常见的).
一个例子:
// callback API declaration's
extern "C" {
typedef unsigned int callback_handle_t;
typedef void (*callback_fcn_t)( void* context, int data1, int data2);
callback_handle_t RegisterCallback( callback_fcn_t, void* context);
void UnregisterCallback( callback_handle_t);
}
// ----------------------------------
// prototype for wrapper function that will receive the callback and
// transform it into a method call
extern "C"
static void doWorkWrapper( void* context, int data1, int data2);
// the class that does the real work
class worker {
public:
worker() {
hCallback = RegisterCallback( doWorkWrapper, this);
}
~worker() {
UnregisterCallback( hCallback);
}
void doWork( int data1, int data2) {
// ...
};
private:
callback_handle_t hCallback;
};
// the wrapper that transforms the callback into a method call
extern "C"
static void doWorkWrapper( void* context, int data1, int data2)
{
worker* pWorker = static_cast<worker*>( context);
pWorker->doWork( data1, data2);
}
Run Code Online (Sandbox Code Playgroud)
检查"[33.2]如何将指针指向成员函数传递给信号处理程序,X事件回调,启动线程/任务的系统调用等?" 在C++ FAQ Lite中:
别.
因为如果没有要调用它的对象,成员函数就没有意义,所以不能直接执行此操作
...
作为现有软件的补丁,使用顶级(非成员)函数作为包装器,该包装器获取通过其他技术获得的对象.