Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ctypes and passing a by reference to a function

I'm trying to use libpcap in python3 using ctypes.

given the following function in C

pcap_lookupnet(dev, &net, &mask, errbuf)

in python I have the following

pcap_lookupnet = pcap.pcap_lookupnet

mask = ctypes.c_uint32
net = ctypes.c_int32

if(pcap_lookupnet(dev,net,mask,errbuf) == -1):
print("Error could not get netmask for device {0}".format(errbuf))
sys.exit(0)

and the error i get is

  File "./libpcap.py", line 63, in <module>
 if(pcap_lookupnet(dev,net,mask,errbuf) == -1):
ctypes.ArgumentError: argument 2: <class 'TypeError'>: Don't know how to convert parameter 2

how do you deal with &blah values ?

like image 457
user961346 Avatar asked Sep 23 '11 14:09

user961346


3 Answers

You need to create instances for net and mask, and use byref to pass them.

mask = ctypes.c_uint32()
net = ctypes.c_int32()
pcap_lookupnet(dev, ctypes.byref(net), ctypes.byref(mask), errbuf)
like image 154
David Heffernan Avatar answered Oct 19 '22 04:10

David Heffernan


You probably need to use ctypes.pointer, like this:

pcap_lookupnet(dev, ctypes.pointer(net), ctypes.pointer(mask), errbuf)

See the ctypes tutorial section on pointers for more information.

I'm assuming you've created ctypes proxies for the other arguments as well. If dev requires a string, for example, you can't simply pass in a Python string; you need to create a ctypes_wchar_p or something along those lines.

like image 23
DNS Avatar answered Oct 19 '22 03:10

DNS


ctypes.c_uint32 is a type. You need an instance:

mask = ctypes.c_uint32()
net = ctypes.c_int32()

Then pass using ctypes.byref:

pcap_lookupnet(dev,ctypes.byref(mask),ctypes.byref(net),errbuf)

You can retrieve the value using mask.value.

like image 40
Mark Tolonen Avatar answered Oct 19 '22 04:10

Mark Tolonen