
On Jul 28, 2011, at 9:01 AM, Clemens Gruber wrote:
Hi,
I am writing a statistical protocol analyzer running under Windows with WinPcap.
The problem is: The pcap_loop function for starting to capture the packets wants a C style callback function, but I need that callback function to have access to several class variables, so this callback function should be a member function. I know that it is not possible to use a member function directly, because of the additional parameter, the pointer to the class.
I thought, maybe I could use boost::function and boost::bind, but I am not sure if my solution is correct, so it would be very nice if some of you guys could just look over it and tell me if this is a good way to do this.
This is my code for starting the capture:
void MyClass::startCapturing() { boost::function < void (u_char *, const struct pcap_pkthdr *, const u_char *) > f; f = boost::bind(&MyClass::packetHandler, this, _1, _2, _3); pcap_handler p = *(f.target<pcap_handler>());
pcap_loop(hnd, 0, p, NULL); }
This the callback function I want pcap_loop to call:
void MyClass::packetHandler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { /* Do something with the packet.. */ }
And this is the signature of the callback argument in the pcap_loop function, as defined in pcap.h: typedef void(*) pcap_handler(u_char *param, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
There's a simple solution that doesn't involve bind - write a "trampoline function". I see from the WinPcap documentation that the first parameter to the callback function is "user supplied", in other words, WinPcap just holds it and passes it to the callback. Here's a sample callback, then. /// Warning - code written in mail client - not compiled, not tested….. void pcap_trampoline ( u_char *param, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data ) { MyClass *me = static_cast<MyClass *> ( param ); me->packetHandler ( header, pkt_data ); // no need to pass 'param' on. } and you set it up like this: MyClass capture_obj; pcap_t *handler; ….. // set up code pcap_loop ( handler, 0, pcap_trampoline, static_cast<u_char *> ( &capture_obj )); Mixing pointer-to-POD and pointer-to-object is not great, but when you've got a C interface, you do what you have to. -- Marshall