如何将指向成员函数的指针传递给C函数?

可能重复:
使用C ++类成员函数作为C回调函数

我正在使用C库(winpcap)编写面向对象的库。 我需要传递当网络数据包作为函数指针到达时调用的回调函数。 我想将一个成员函数指针传递给winpcap,以保持我的设计对象的方向,并允许不同的对象接收不同的数据包。 但是据我所知,成员函数具有不同的调用约定,因此不能传递给C函数。 有没有办法来解决这个问题。 我使用boost :: bind进行的实验(除了试验和错误之外我几乎无法使用)并不富有成效。

有没有办法改变成员函数的调用约定?

这是我现在使用的回调函数的定义以及它实际传递给winpcap的定义

void pcapCallback( byte* param, const struct pcap_pkthdr* header, const byte* pkt_data ); pcap_loop( adhandle, 0, pcapCallback, NULL ); 

pcap_loop只接受函数的名称(目前在全局范围内)。 这是函数指针参数的定义( pcap_loop的第3个参数)。 由于这是第三方代码,我无法真正改变这一点。 我必须有一个可以采用这种forms的成员函数:

 typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); 

据我所知,成员函数将使用thiscall,而c函数指针需要一个cdecl

请参阅详细的主题

如何实现对静态C ++成员函数的回调?

如何实现对非静态C ++成员函数的回调?

http://www.newty.de/fpt/callback.html

您只能将static成员函数传递给C API。

如果要将C API调用成为成员函数,则必须传递两个数据:(静态成员)函数和要为其调用的对象。

通常,C API回调具有某种forms的“用户数据”,通常是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(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); } 

与全局数据一样,如果回调的多个实例存活,则这是危险的。 我试图尽量减少伤害,以便在它们的生命周期嵌套时起作用。 但是,其他任何事情都会受到伤害。