Ошибка компиляции
, invalid use of member (did you forget the ‘&’)
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.219] |
|
|
Ошибка компиляции
, invalid use of member (did you forget the ‘&’)
|
|
|
|
|
Народ помогите. Пишу программу, которая должна определить все МАК и IP адрес, что-то на подобии tcpdump. Платформа Ubuntu 10.04.
Есть программный код, который определяет МАК адреса. Решил его переделать его из С в С + +, соответственно с классом и H файлом ![]() ![]() #include <pcap.h> #include <stdlib.h> #include <signal.h> #include <netinet/ip.h> #include <netinet/if_ether.h> #include <arpa/inet.h> #include <netinet/ether.h> #include <unistd.h> int child_pid = 0; void print_eth_addr(void *addr) { printf("%s\n", ether_ntoa((struct ether_addr *)addr)); kill(child_pid, 9); exit(0); } void find_eth_addr(struct in_addr *search_ip, const struct pcap_pkthdr* pkthdr, const u_char *packet) { struct ether_header *eth_hdr = (struct ether_header *)packet; if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP) { struct ip *ip_hdr = (struct ip *)(packet + sizeof(struct ether_header)); if (ip_hdr->ip_dst.s_addr == search_ip->s_addr) print_eth_addr(eth_hdr->ether_dhost); if (ip_hdr->ip_src.s_addr == search_ip->s_addr) print_eth_addr(eth_hdr->ether_shost); } } int main(int argc, char **argv) { char *dev, errbuf[PCAP_ERRBUF_SIZE]; pcap_t* descr; bpf_u_int32 maskp, netp; if (argc < 2) { printf("Usage: %s <ip> [interface]\n", argv[0]); return 1; } if (argc == 2 && !(dev = pcap_lookupdev(errbuf))) { fprintf(stderr, "%s\n", errbuf); return 1; } else if (argc == 3) { dev = argv[2]; } pcap_lookupnet(dev,&netp,&maskp,errbuf); if (!(descr = pcap_open_live(dev, BUFSIZ, 1, -1, errbuf))) { printf("pcap_open_live(): %s\n", errbuf); return 1; } struct in_addr search_ip; if (!inet_aton(argv[1], &search_ip)) { fprintf(stderr, "bad ip\n"); exit(1); } int pid = fork(); if (pid == 0) { while (1) { struct sockaddr_in sin; sin.sin_family = PF_INET; inet_aton(argv[1], &sin.sin_addr); sin.sin_port = htons(1); int s = socket(PF_INET, SOCK_STREAM, 0); connect(s, (struct sockaddr *)&sin, sizeof(sin)); usleep(100000); } } else { child_pid = pid; //pcap_loop(descr, -1, (pcap_handler)find_eth_addr, (void *)&search_ip); pcap_loop(descr, -1, (pcap_handler)find_eth_addr, (u_char *)&search_ip); } return 0; } Код рабочий, дальше идет моя интерпретация. Соответственно h и cpp. local_mac.h ![]() ![]() #pragma once #ifndef BASIC_H #define BASIC_H #include <pcap.h> #include <stdlib.h> #include <signal.h> #include <netinet/ip.h> #include <netinet/if_ether.h> #include <arpa/inet.h> #include <netinet/ether.h> #include <unistd.h> int child_pid = 0; class LocalMacAdd { public: LocalMacAdd(int ARGC, char **ARGV); int GetAddres(); private: void print_eth_addr(void *addr); void find_eth_addr(struct in_addr *search_ip, const struct pcap_pkthdr* pkthdr, const u_char *packet); char *dev, *ErrorBuffer,**argv; struct in_addr search_ip; pcap_t* descr; bpf_u_int32 maskp, netp; int argc; }; #endif local_mac.cpp ![]() ![]() #include "local_mac.h" #include <iostream> using namespace std; LocalMacAdd::LocalMacAdd(int ARGC, char **ARGV) { argc = ARGC; argv = ARGV; } void LocalMacAdd::print_eth_addr(void *addr) { cout << " " << ether_ntoa((struct ether_addr *)addr) << " " << endl; kill(child_pid, 9); exit(0); } void LocalMacAdd::find_eth_addr(struct in_addr *search_ip, const struct pcap_pkthdr* pkthdr, const u_char *packet) { struct ether_header *eth_hdr = (struct ether_header *)packet; if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP) { struct ip *ip_hdr = (struct ip *)(packet + sizeof(struct ether_header)); if (ip_hdr->ip_dst.s_addr == search_ip->s_addr) print_eth_addr(eth_hdr->ether_dhost); if (ip_hdr->ip_src.s_addr == search_ip->s_addr) print_eth_addr(eth_hdr->ether_shost); } } int LocalMacAdd::GetAddres()//int argc, char **argv) { ErrorBuffer = new char[PCAP_ERRBUF_SIZE]; if (argc < 2) { cout << " Usage: <ip> [interface]\n" << argv[0] << endl; return 1; } if (argc == 2 && !(dev = pcap_lookupdev(ErrorBuffer))) { cerr << " " << ErrorBuffer << " " << endl; return 1; } else if (argc == 3) { dev = argv[2]; } pcap_lookupnet(dev,&netp,&maskp,ErrorBuffer); if (!(descr = pcap_open_live(dev, BUFSIZ, 1, -1, ErrorBuffer))) { cout << "pcap_open_live(): \n " << ErrorBuffer << endl; return 1; } //struct in_addr search_ip; if (!inet_aton(argv[1], &search_ip)) { cerr << "bad ip\n" << endl; exit(1); } int pid = fork(); if (pid == 0) { while (1) { struct sockaddr_in sin; sin.sin_family = PF_INET; inet_aton(argv[1], &sin.sin_addr); sin.sin_port = htons(1); int s = socket(PF_INET, SOCK_STREAM, 0); connect(s, (struct sockaddr *)&sin, sizeof(sin)); usleep(100000); } } else { child_pid = pid; // u_char * temp =(u_char *) search_ip; pcap_loop(descr, -1, (pcap_handler)find_eth_addr,((u_char *) (&search_ip)) ); //pcap_loop(descr, -1, (pcap_handler)find_eth_addr,(u_char *)&search_ip); } } Сама ошибка находится в строке ![]() ![]() pcap_loop(descr, -1, (pcap_handler)find_eth_addr,((u_char *) (&search_ip)) ); local_mac.cpp:69: error: invalid use of member (did you forget the ‘&’?) сигнатура функции ![]() ![]() int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) Возможно кто-то чем-то поможет |
|
Сообщ.
#2
,
|
|
|
|
LocalMacAdd::find_eth_addr() - это не свободная функция, это метод класса, и поэтому да, указатели на них должны браться явно. Но не это главное. Взяв указатель на него, ты получишь не тип pcap_handler. Сравни:
![]() ![]() typedef void ( *func_ptr )(struct in_addr *, const struct pcap_pkthdr*, const u_char *); typedef void (LocalMacAdd::*member_ptr)(struct in_addr *, const struct pcap_pkthdr*, const u_char *); |
|
Сообщ.
#3
,
|
|
|
|
Цитата Qraizer @ А если функцию GetAddres () объявить вне класса, и в ней инициализировать объект класса LocalMacAdd? |
|
Сообщ.
#4
,
|
|
|
|
Что-то я смутно представляю, как это тебе поможет. Давай я набросаю идею, а ты посмотри, что из этого будет полезным.
Обычно в случаях, когда легаси-коду требуется передать метода класса, коллбэком делают всё-таки свободную функцию. Или статический метод, их сигнатуры от this не зависят и в общем-то совместимы со свободными функциями. При этом this как-то куда-то передают на сохранение, чтобы в этой свободной функции его достать и использовать по назначению - вызвать с ним требуемый его метод. Способов много. Например, в WinAPI у подавляющего большинства коллбэков в параметрах обязательно предусмотрен некий void*, каковой самим WinAPI не используется и просто передаётся из точки API-вызова в коллбэк. Например (для большей ясности определения чуть изменены): ![]() ![]() BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam); typedef BOOL (*WNDENUMPROC)(HWND hwnd, LPARAM lParam); ![]() ![]() struct in_addr_proxy { struct in_addr* search_ip; LocalMacAdd* it_is_this; in_addr_proxy(struct in_addr* ip, LocalMacAdd* obj): search_ip(ip), it_is_this(obj) {} operator in_addr* () const { return search_ip; } virtual ~in_addr_proxy() {} }; void find_eth_addr_proxy(struct in_addr *search_ip, const struct pcap_pkthdr* pkthdr, const u_char *packet) { in_addr_proxy *restored = (in_addr_proxy *)((char*)search_ip - offsetof(in_addr_proxy, search_ip)); if (typeid(*restored) != typeid(in_addr_proxy)) throw std::invalid_argument("find_eth_addr_proxy(): 1st param hasn't the in_addr_proxy type"); restored->it_is_this->find_eth_addr(restored->search_ip, pkthdr, packet); } /* ... */ pcap_loop(descr, -1, find_eth_addr_proxy, (u_char*)(in_addr*)&(in_addr_proxy(&search_ip, this))); P.S. Могут присутствовать даже опечатки. |
|
Сообщ.
#5
,
|
|
|
|
Цитата Qraizer @ Что-то я смутно представляю, как это тебе поможет. Давай я набросаю идею, а ты посмотри, что из этого будет полезным. Обычно в случаях, когда легаси-коду требуется передать метода класса, коллбэком делают всё-таки свободную функцию. Или статический метод, их сигнатуры от this не зависят и в общем-то совместимы со свободными функциями. При этом this как-то куда-то передают на сохранение, чтобы в этой свободной функции его достать и использовать по назначению - вызвать с ним требуемый его метод. Способов много. Например, в WinAPI у подавляющего большинства коллбэков в параметрах обязательно предусмотрен некий void*, каковой самим WinAPI не используется и просто передаётся из точки API-вызова в коллбэк. Например (для большей ясности определения чуть изменены): ![]() ![]() BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam); typedef BOOL (*WNDENUMPROC)(HWND hwnd, LPARAM lParam); ![]() ![]() struct in_addr_proxy { struct in_addr* search_ip; LocalMacAdd* it_is_this; in_addr_proxy(struct in_addr* ip, LocalMacAdd* obj): search_ip(ip), it_is_this(obj) {} operator in_addr* () const { return search_ip; } virtual ~in_addr_proxy() {} }; void find_eth_addr_proxy(struct in_addr *search_ip, const struct pcap_pkthdr* pkthdr, const u_char *packet) { in_addr_proxy *restored = (in_addr_proxy *)((char*)search_ip - offsetof(in_addr_proxy, search_ip)); if (typeid(*restored) != typeid(in_addr_proxy)) throw std::invalid_argument("find_eth_addr_proxy(): 1st param hasn't the in_addr_proxy type"); restored->it_is_this->find_eth_addr(restored->search_ip, pkthdr, packet); } /* ... */ pcap_loop(descr, -1, find_eth_addr_proxy, (u_char*)(in_addr*)&(in_addr_proxy(&search_ip, this))); P.S. Могут присутствовать даже опечатки. Спасибо за ответ, но я уже просто напросто для этого решения исключил класс, WinAPI не подойдет так как платформа Ubuntu 10.04. Запустил твое решение, просто без дебага выдало следующие ошибки, возможно наследникам пригодится ![]() ![]() ![]() root@ubuntu:/home/administrator/Desktop/projectM# g++ -o main main.cpp basic_info.cpp local_mac.cpp -lpcap local_mac.cpp: In function ‘void find_eth_addr_proxy(in_addr*, const pcap_pkthdr*, const u_char*)’: local_mac.cpp:38: warning: invalid access to non-static data member ‘in_addr_proxy::search_ip’ of NULL object local_mac.cpp:38: warning: (perhaps the ‘offsetof’ macro was used incorrectly) local_mac.cpp:40: error: ‘invalid_argument’ was not declared in this scope local_mac.cpp:15: error: ‘void LocalMacAdd::find_eth_addr(in_addr*, const pcap_pkthdr*, const u_char*)’ is private local_mac.cpp:41: error: within this context local_mac.cpp: In member function ‘int LocalMacAdd::GetAddres()’: local_mac.cpp:87: error: invalid use of member (did you forget the ‘&’ ) Спасибо за быстрый ответ |
|
Сообщ.
#6
,
|
|
|
|
Похоже, очередной раз идейный код был тупо использован в качестве готового решения. А подумать?
Я ж говорил, что WinAPI тут для примера. Просто демонстрация дизайна кода, как обычно дружатся объекты с простым структурным API. Что касается остального... построчно: |
|
Сообщ.
#7
,
|
|
|
|
Цитата Qraizer @ Похоже, очередной раз идейный код был тупо использован в качестве готового решения. А подумать? Я ж говорил, что WinAPI тут для примера. Просто демонстрация дизайна кода, как обычно дружатся объекты с простым структурным API. Что касается остального... построчно: Друг, подумать всегда полезно но мне нужно завтра уже сдавать |