通过指针从Python中传递到C结构

2024-04-29 14:50:20 发布

您现在位置:Python中文网/ 问答频道 /正文

不知道如何通过Python中的指针将结构传递给C函数。 以下是我所拥有的(这是为nanomsg-python项目实现nn_recvmsg的更大努力的一部分):

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

这给了我:

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

从输出中,我看到参数类型与函数期望的类型相同。然而,它仍然失败了。你知道吗

下面是我正在实现的函数的结构定义和完整代码:

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

Tags: selflentypemsgnnctypesppprint