Boost logo

Boost Users :

Subject: Re: [Boost-users] pcap_loop callback with boost::function and boost::bind
From: Marshall Clow (mclow.lists_at_[hidden])
Date: 2011-07-28 12:28:28


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

        


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net