How to pass a pointer to a member function of function C?

Possible duplicate:
Using C ++ Class Member Function as C Callback Function

I am writing an object oriented library using the C library (winpcap). I need to pass a callback function that is called when a network packet arrives as a function pointer. I would like to pass a member function pointer to winpcap in order to support the design object and allow different objects to receive different packages. However, the member functions, as I understand it, have a different calling convention and therefore cannot be passed to C. There is a way to fix this. My experiments with boost :: bind (which I can hardly use except trial and error) are not fruitful.

Is there a way to change the calling convention of a member function?

This is the definition of the callback function that I am using now, and its actual transfer to winpcap

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

pcap_loop simply accepts the name of the function (which is now in the global scope). This is the definition of a function pointer parameter (3rd parameter pcap_loop ). Since this is third-party code, I cannot change this. I would have to have a member function that can take this form:

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

As far as I understand, the member function will use thiscall, and the c function pointer wants cdecl

+4
source share
3 answers

Please refer to the detailed topic on

How to implement a callback for a static function of a C ++ member?

How to implement a callback for a non-static member function in C ++?

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

+4
source

You can only pass static member functions in the C API.

+4
source

If you want the C API to call a member function, you need to pass two pieces of data: the function (static member) and the object for which it must be called.

Typically, C API callbacks have some form of "user data", often void* , through which you can tunnel your object address:

 // 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); } 

That pcapCallback does not look like it has user data, unless it is that param . If this is true, you will need to store the address of the callback object in some global variable before calling the API. Something like that:

 // 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); } 

As always with global data, it is dangerous if more than one callback instance is alive. I tried to minimize the harm so that it would work if their life time was invested. However, everything else will hurt.

+2
source

Source: https://habr.com/ru/post/1313742/


All Articles