2015-12-12 2 views
2

Я пытаюсь использовать функцию pcap_loop в libpcab библиотеке в Linux с этим прототипом:обратного вызова в pcap_loop

int pcap_loop(pcap_t *, int, pcap_handler, u_char *); 

pcap_pkthdr является функцией указателя:

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

В моей программе, у меня есть определен следующий метод в классе SniffEthernet:

void SniffEthernet::got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet); 

Теперь призывающую pcap_loop, как показано ниже

pcap_loop(handle, num_packets, this->got_packet, NULL); 

дает мне ошибку следующее время компиляции:

SniffEthernet.cc:139:58: error: cannot convert ‘VENTOS::SniffEthernet::got_packet’ from type ‘void (VENTOS::SniffEthernet::)(u_char*, const pcap_pkthdr*, const u_char*) {aka void (VENTOS::SniffEthernet::)(unsigned char*, const pcap_pkthdr*, const unsigned char*)}’ to type ‘pcap_handler {aka void (*)(unsigned char*, const pcap_pkthdr*, const unsigned char*)}’ 

Что я делаю неправильно здесь?

Редактировать: Я нашел аналогичный пост here.

ответ

3

Ваша функция обратного вызова не может быть функцией-членом (методом). Не забывайте, что функции-члены всегда имеют скрытый параметр this.

Функция обратного вызова должна быть либо функцией уровня пространства имен, либо статическим членом вашего класса.

Если вы хотите, чтобы ваш объект доступен для функции CB, вы можете использовать user элемент (последний аргумент pcap_loop(), первый член функции обратного вызова), при правильных приведениях типов, передавать произвольные данные, которые, в вашем случае, может быть объектом вы используете для захвата.

Код ниже неполные и непроверенных, но может дать вам идею.

class SniffEther { 
    private: 
     pcap_t *cap_handler; 
     char errbuf[PCAP_ERRBUF_SIZE]; 
     /* capture-related data members (properties) */ 

    public: 
     static friend void pkt_callback(u_char *user, const pcap_pkthdr *hdr, const u_char *bytes){ 
      SniffEther *sniffer=reinterpret_cast<SniffEther *>(user); 
      /* 
       Process header and bytes. 

       You can call things like sniffer->somemethod(), and also 
       access sniffer->someproperty. 
      */ 
     } 

     // constructor 
     SniffEther(const char *if_name){ 
      cap_handler=pcap_create(if_name, errbuf); 
      if(!cap_handler) 
       throw runtime_error(errbuf); 
      /* Set the many pcap_options (see pcap(3)). */ 
      if(pcap_activate(cap_handler)!=0){ 
       string error(pcap_geterr(cap_handler)); 
       pcap_close(cap_handler); 
       throw runtime_error(error); 
      } 
     } 

     ~SniffEther(){ 
      if(cap_handler) 
       pcap_close(cap_handler); 
     } 

     void capture_loop(int pkt_count=-1){ 
      if(
       pcap_loop(
        cap_handler, pkt_count, pkt_callback, 
        reinterpret_cast<*u_char>(this) 
       )==-1 
      ) 
       throw runtime_error(pcap_geterr(cap_handler)); 
     } 
}; 
+0

Удивительный ответ. Вызов reinterpret_cast в вызове pcap_loop() имеет неуправляемый оператор разыменования, но не работает этот код. –