如果要让 C API 调用成员函数,则必须传递两条数据:(静态成员)函数和要调用它的对象。
通常,C API 回调具有某种形式的“用户数据”,通常是 a void*
,您可以通过它隧道访问对象的地址:
// Beware, brain-compiled code ahead!
typedef void (*callback)(int data, void* user_data);
void f(callback cb, void* user_data);
class cpp_callback {
public:
virtual ~cpp_callback() {} // sometimes needed
void cb(int data) = 0;
callback* get_callback() const {return &cb_;}
private
static void cb_(int data, void* user_data)
{
cpp_callback* that = reinterpret_cast<my_cpp_callback*>(user_Data);
that->cb(data);
}
};
class my_callback {
public:
void cb(int data)
{
// deal with data
}
};
void g()
{
my_callback cb;
f(cb.get_callback(), &cb);
}
但是,这pcapCallback
看起来好像没有用户数据,除非那是真实param
的。如果确实如此,则必须在调用 API 之前将回调对象的地址存储在某个全局变量中。像这样的东西:
// Beware, brain-compiled code ahead!
typedef void (*callback)(int data);
void f(callback cb);
class cpp_callback {
public:
cpp_callback() : the_old_cb_(this) {std::swap(the_cb_,the_old_cb_);}
virtual ~cpp_callback() {std::swap(the_cb_,the_old_cb_);}
void cb(int data) = 0;
callback* get_callback() const {return &cb_;}
private
static cpp_callback* the_cb_;
cpp_callback* the_old_cb_;
static void cb_(int data, void* user_data)
{
the_cb_->cb(data);
}
};
class my_callback {
public:
void cb(int data) { /* deal with data */ }
};
void g()
{
my_callback cb;
f(cb.get_callback(), &cb);
}
与全局数据一样,如果不止一个回调实例处于活动状态,这是很危险的。我试图将伤害降到最低,这样如果它们的生命周期是嵌套的,它就会起作用。但是,其他任何事情都会受到伤害。