使用 ctypes 处理回调

发布于 2024-12-07 15:24:44 字数 2316 浏览 0 评论 0原文

我正在尝试使用 ctypes 将 libpcap 映射到 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))

“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)

I'm attempting to map libpcap using ctypes to python3.2 and I'm having a problem using callbacks with pcap_loop... here is the code ..

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))

it seems to have a problem with the 2nd parameter which is the "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

THis is my first time doing work with ctypes so I'm rather confused at this point.

...... EDIT..........

So the prototype is trying to accept a pointer to a list of arguments. so I tried doing a pointer to a instance that can take a list but now I'm getting a new error..

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))

and this is the error

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

哑剧 2024-12-14 15:24:44

回调采用 int,因此使用 ctypes.c_int 声明回调原型并传递 1。请注意,您可以传递一个普通的 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))

The callback takes an int, so declare the callback prototype with ctypes.c_int and pass one. Note you can pass a plain Python integer and ctypes will take care of marshaling it correctly to the C function. It doesn't have to be a c_int instance. Your c_int_hack is unnecessary.

Update

Here's an excerpt of what I got to work:

# 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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文