I'm trying to convert a 16 byte blob of data returned by socket..net_pton into a ctypes array of unsigned bytes. My data structure looks like this:
class in6_addr(ctypes.Structure): _fields_ = (("Byte", ctypes.c_ubyte * 16),)
And the blob is just:
data = socket.inet_pton(socket.AF_INET6, "2001::3")
However, these attempts get errors:
sin6 = in6_addr() # TypeError: expected c_ubyte_Array_16 instance, got str sin6.Byte = data # TypeError: cast() argument 2 must be a pointer type, not c_ubyte_Array_16 sin6.Byte = ctypes.cast(data, ctypes.c_ubyte * 16) # TypeError: incompatible types, LP_c_ubyte instance instead of c_ubyte_Array_16 instance sin6.Byte = ctypes.cast(data, ctypes.POINTER(ctypes.c_ubyte))
All of the code: http://codepad.org/2cjyVXBA
Any ideas what type I need to cast to?
I might be completely wrong here (and it does seem a bit complex) but this works for me:
sin6.Byte = (ctypes.c_ubyte*16)(*list(bytearray(data)))
I had to convert the data into a list of integers and unpack them for the constructor. There must be an easier way!
Arguably easier:
sin6.Byte = cast(data, ctypes.POINTER(ctypes.c_ubyte * 16)).contents
or:
sin6.Byte = (ctypes.c_ubyte * 16)(*[x for x in data])
Using bytes stream:
import io
io.BytesIO(data).readinto(sin6.Byte)
And since the considered structure contains the single field, the field name can be omited:
sin6 = cast(data, ctypes.POINTER(ctypes.c_ubyte * 16)).contents
sin6 = (ctypes.c_ubyte * 16)(*[x for x in data])
io.BytesIO(data).readinto(sin6)
Easiest way:
import ctypes
import socket
class in6_addr(ctypes.Structure):
_fields_ = (("Byte", ctypes.c_ubyte * 16),)
data = socket.inet_pton(socket.AF_INET6, "2001::3")
sin6 = in6_addr()
sin6.Byte[:] = data # copy the data into a complete slice of the array
A couple of helper methods make the class easier to use as well:
import ctypes
import socket
class in6_addr(ctypes.Structure):
_fields_ = ("Byte", ctypes.c_ubyte * 16),
def __init__(self, data):
self.Byte[:] = data
def __repr__(self):
return f'in6_addr(Bytes=bytes({list(self.Byte)}))'
data = socket.inet_pton(socket.AF_INET6, "2001::3")
sin6 = in6_addr(data)
print(sin6)
Output:
in6_addr(Bytes=bytes([32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.