обработка обратного вызова с помощью ctypes

#python-3.x #ctypes #libpcap

#python-3.x #ctypes #libpcap

Вопрос:

Я пытаюсь сопоставить libpcap с использованием ctypes с python3.2, и у меня возникла проблема с использованием обратных вызовов с помощью pcap_loop … вот код ..

 class c_int_hack:
def from_param(self, *args):
    return ctypes.c_void_p
#void got_packet(u_char *args, const struct pcap_pkthdr *header,
#       const u_char *packet)  

CALLBACK=ctypes.CFUNCTYPE(ctypes.c_void_p,c_int_hack,ctypes.pointer(pkthdr),ctypes.POINTER(ctypes.c_ubyte))

#int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
def process(user,pkthdr,packet):
print("In callback:")
print("pkthdr[0:7]:",pkthdr.contents.len)
print("packet6:%2x",packet[6])
print("packet7:%2x",packet[7])
print("packet8:%2x",packet[8])
print("packet9:%2x",packet[9])
print("packet10:%2x",packet[10])
print("packet11:%2x",packet[11])

got_packet=CALLBACK(process)

if(pcap_loop(handle,ctypes.c_int(10), got_packet,"what") == -1):
    err = pcap_geterr(handle)
print("pcap_loop error: {0}".format(err))
  

похоже, у него проблема со 2-м параметром, который является «c_int_hack»

 Got Required netmask
Pcap open live worked!
Filter Compiled!
Filter installed!
Traceback (most recent call last):
 File "./libpcap.py", line 72, in <module>
 CALLBACK=ctypes.CFUNCTYPE(ctypes.c_void_p,c_int_hack,ctypes.pointer(pkthdr),ctypes.POINTER(ctypes.c_ubyte))
File "/usr/lib/python3.2/ctypes/__init__.py", line 99, in CFUNCTYPE
return _c_functype_cache[(restype, argtypes, flags)]
TypeError: unhashable type
  

Я впервые работаю с ctypes, поэтому на данный момент я довольно смущен.

…… Редактировать……….

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

 class ListPOINTER(object):
'''Just like a POINTER but accept a list of ctype as an argument'''
def __init__(self, etype):
    self.etype = etype

def from_param(self, param):
    if isinstance(param, (list,tuple)):
        return (self.etype * len(param))(*param)
#void got_packet(u_char *args, const struct pcap_pkthdr *header,
#       const u_char *packet)


args=ListPOINTER()

CALLBACK = ctypes.CFUNCTYPE(ctypes.c_void_p,args(ctypes.c_char_p),ctypes.pointer(pkthdr),ctypes.POINTER(ctypes.c_ubyte))
  

и это ошибка

 Got Required netmask
Pcap open live worked!
Filter Compiled!
Filter installed!
Traceback (most recent call last):
File "./libpcap.py", line 81, in <module>
args=ListPOINTER()
TypeError: __init__() takes exactly 2 arguments (1 given)
  

Ответ №1:

Обратный вызов принимает значение an int , поэтому объявите прототип обратного вызова с ctypes.c_int помощью и передайте его. Обратите внимание, что вы можете передать простое целое число Python, и ctypes позаботится о его правильном маршалировании в функцию C. Это не обязательно должен быть c_int экземпляр. Ваш c_int_hack не нужен.

Обновить

Вот выдержка из того, что я должен работать:

 # struct pcap_pkthdr
class Header(Structure):
    _fields_ = [
        ('ts',c_uint),
        ('caplen',c_uint),
        ('len',c_uint)]

# Something for user data
class User(Structure):
    _fields_ = [
        ('one',c_uint),
        ('two',c_uint),
        ('three',c_char_p)]

# callback type
# To Python, a pointer is a pointer...so I lie and tell it the actual type
# instead of the byte pointers in the original function definition, indicating
# the user structure and the data buffer size.
PKTHANDLER = CFUNCTYPE(None,POINTER(User),POINTER(Header),POINTER(c_ubyte*65536))

def packet_handler(param,header,data):
    print(param.contents.three)
    print(header.contents.ts,header.contents.caplen,header.contents.len)
    print(data.contents[:10])
    print()

ph = PKTHANDLER(packet_handler)
user = User(1,2,b"hello")
wpcap.pcap_loop(h,0,ph,byref(user))
  

Комментарии:

1. на самом деле он ожидает список аргументов. «c_int_hack» просто неправильно назван. void got_packet(u_char *аргументы, const struct pcap_pkthdr *заголовок,const u_char *пакет) — это формат обратного вызова . если я создаю указатель на класс, который принимает список, я могу получить сообщение об ошибке, в котором говорится, что тип не является хешируемым.

2. Обновлено примером, который передает структуру пользователя. Это то, что вы пытаетесь сделать?