全局变量
正如其他人所提到的,您需要一个全局(静态成员是作为变量成员隐藏的全局),当然,如果您需要多个对象在所述回调中使用不同的参数,它就行不通。
回调中的上下文参数
AC 库可能会提供一个void *
或一些类似的上下文。在这种情况下,请使用该功能。
例如,ffmpeg 库支持读取数据的回调,其定义如下:
int(*read_packet)(void *opaque, uint8_t *buf, int buf_size);
该opaque
参数可以设置为this
。在您的回调中,只需将其转换回您的类型(您的班级名称)。
Calback 中的库上下文参数
AC 库可能会使用其对象(struct
指针)调用您的回调。假设您有一个名为的库example
,它提供一个名为的类型example_t
并定义如下回调:
callback(example_t *e, int param);
然后,您可以将您的上下文(也称为this
指针)放在该example_t
结构中,并在您的回调中取回它。
串行调用
假设您只有一个线程使用该特定 C 库,并且只有在调用库中的函数时才能触发回调(即,您不会在某个随机时间点触发事件),您仍然可以使用全局变量. 您需要做的是在每次调用之前将当前对象保存在全局中。像这样的东西:
object_i_am_working_with = this;
make_a_call_to_that_library();
这样,在回调内部,您始终可以访问object_i_am_working_with
指针。这在多线程应用程序或库在后台自动生成事件(即按键、来自网络的数据包、计时器等)时不起作用。
每个对象一个线程 (C++11 起)
这是多线程环境中的一个有趣的解决方案。当您没有以前的解决方案可用时,您可以使用线程来解决问题。
在 C++11 中,有一个新的特殊说明符,名为thread_local
. 在过去,您必须手动处理特定于每个线程实现的事情......现在您可以这样做:
thread_local Class_w_callback * callback_context = nullptr;
然后,在您的回调中,您可以将callback_context
用作返回Class_w_callback
类的指针。
当然,这意味着您需要为每个创建的对象创建一个线程。这在您的环境中可能不可行。就我而言,我的组件都在运行自己的循环,因此每个组件都有自己的thread_local
环境。
请注意,如果库自动生成事件,您可能也不能这样做。
带线程的旧方法(和 C 解决方案)
正如我上面提到的,在过去,您必须自己管理本地线程环境。使用pthread
(基于 Linux),您可以通过以下方式访问特定于线程的数据pthread_getspecific()
:
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
这利用了动态分配的内存。这可能thread_local
是 Linux 下 g++ 的实现方式。
在 MS-Windows 下,您可能会使用TlsAlloc函数。