Can't figure out how to pass a structure by pointer to a C function from Python. Here is what I have (it's a part of bigger effort of implementing nn_recvmsg for nanomsg-python project):
...
msgHdr = NN_MSGHDR(iovecList)
pointer_type = ctypes.POINTER(NN_MSGHDR)
pp = pointer_type.from_address(ctypes.addressof(msgHdr))
print("argument type: "+str(pp))
print("function arguments: "+str(_nn_recvmsg.argtypes))
rtn = _nn_recvmsg(socket, pp, 0)
...
Which gives me:
argument type: <_nanomsg_ctypes.LP_NN_MSGHDR object at 0x10b6d8d40>
function arguments: (<class 'ctypes.c_int'>, <class '_nanomsg_ctypes.LP_NN_MSGHDR'>, <class 'ctypes.c_int'>)
Traceback (most recent call last):
File "./test.py", line 11, in <module>
nnc.nn_recvmsg(s, [4, frameSize])
File "/Users/peetonn/Documents/Work/ptn-nanomsg-python/_nanomsg_ctypes/__init__.py", line 311, in nn_recvmsg
rtn = _nn_recvmsg(socket, pp, 0)
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: wrong type
from the output, I see that argument type is the same as the function would expect it to be. However, it still fails.
Below are structure definitions and full code for the function I'm implementing:
class NN_IOVEC(ctypes.Structure):
_fields_ = [("iov_base", ctypes.c_void_p),
("iov_len", ctypes.c_size_t)]
class NN_MSGHDR(ctypes.Structure):
_fields_ = [("msg_iov", ctypes.POINTER(NN_IOVEC)), # ctypes.c_void_p),
("msg_iovlen", ctypes.c_int),
("msg_control", ctypes.c_void_p),
("msg_controllen", ctypes.c_size_t)]
def __init__(self, iovecList):
elems = (NN_IOVEC * len(iovecList))()
self.msg_iovlen = len(iovecList)
self.msg_iov = ctypes.cast(elems, ctypes.POINTER(NN_IOVEC))
for i in range(0, len(iovecList)):
self.msg_iov[i].iov_base = iovecList[i].iov_base
self.msg_iov[i].iov_len = iovecList[i].iov_len
self.msg_controllen = 0
self.msg_control = 0
def nn_recvmsg(socket, sizes = None):
"receive message/messages"
if sizes:
iovecList = []
for sz in sizes:
iovec = NN_IOVEC()
iovec.iov_len = sz
buf = (ctypes.c_char * sz)()
iovec.iov_base = ctypes.cast(buf, ctypes.c_void_p)
iovecList.append(iovec)
msgHdr = NN_MSGHDR(iovecList)
pointer_type = ctypes.POINTER(NN_MSGHDR)
pp = pointer_type.from_address(ctypes.addressof(msgHdr))
print("argument type: "+str(pp))
print("function arguments: "+str(_nn_recvmsg.argtypes))
rtn = _nn_recvmsg(socket, ctypes.byref(pp), 0)
print("here's the result: "+str(rtn))
if rtn < 0 :
print(nn_strerror(nn_errno()))
else:
pass # tbd