3

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
peetonn
  • 2,942
  • 4
  • 32
  • 49
  • hmmm I cannot quite put my finger on it but using `pp = pointer_type.from_address` feels wrong you should be able to use pointer_type directly in `_nn_recvmsg` . Do you have a git repo of your test, it's hard to help without being able to have something runnable – Ahmed Masud Oct 30 '17 at 23:55
  • @AhmedMasud sure, here it is https://github.com/peetonn/nanomsg-python/commits/master tried `pointer()` and `byref()` - same problem – peetonn Oct 31 '17 at 00:03
  • @AhmedMasud I added c++ tests as well, but you need to install nanomsg library to build them - https://github.com/nanomsg/nanomsg – peetonn Oct 31 '17 at 00:12
  • Okay I have figured out the issue. :P – Ahmed Masud Oct 31 '17 at 07:12
  • The error you're getting is actually about argument 1 (Socket) and not the NN_MSGHDR ... You need to create a wrapper in the Socket class in nanomsg/__init__.py ... I have pushed a more verbose version of the repo to github at https://github.com/ahmed-masud/nanomsg-python/tree/nn_recvmsg-wip I can help you debug it there, and we can post the final solution here later – Ahmed Masud Oct 31 '17 at 07:21
  • oh damn! i tried to find somewhere how python numerates arguments but couldn't find anywhere and based on other examples online assumed it numerates starting from 0. thanks a lot! I'll share what I'll have – peetonn Oct 31 '17 at 16:10
  • @AhmedMasud I've implemented this function - https://github.com/peetonn/nanomsg-python/commit/287881595712b14bb09cc62bc5f77fe1680d4e78 there might be something not elegant with the buffers, since I don't know python... – peetonn Oct 31 '17 at 21:40

0 Answers0