如何从C函数签名确定Python3 ctypes.argtypes?

如何从C函数签名确定Python3 ctypes.argtypes?,python,python-3.x,ctypes,Python,Python 3.x,Ctypes,我正在向第三方DLL编写ctypes接口(我无法控制DLL) 我的代码似乎正常工作,但我担心我设置的.argtypes错误 我试图调用的C函数的签名是: int GetData(unsigned short option, unsigned char* buffer, int bufferLength, int &actualLength); 选项表示请求的数据类型,缓冲区指向缓冲区I提供,缓冲区长度是缓冲区的长度(以字节为单位) DLL函数写入缓冲区,并将实际写入的字节数放入actu

我正在向第三方DLL编写ctypes接口(我无法控制DLL)

我的代码似乎正常工作,但我担心我设置的
.argtypes
错误

我试图调用的C函数的签名是:

int GetData(unsigned short option, unsigned char* buffer, int bufferLength, int &actualLength);
选项
表示请求的数据类型,
缓冲区
指向缓冲区I提供,
缓冲区长度
是缓冲区的长度(以字节为单位)

DLL函数写入缓冲区,并将实际写入的字节数放入
actualLength

我的代码:

import ctypes

dll = ctypes.CDLL("dll_name.dll")

def GetData(option):

    BUFSIZE = 6

    buf = bytearray(BUFSIZE)

    ptr_to_buf = (ctypes.c_char*len(buf)).from_buffer(buf)

    actualLength = ctypes.c_int()

    dll.GetData.argtypes = (ctypes.c_ushort, 
                            ctypes.c_char_p, 
                            ctypes.c_int, 
                            ctypes.POINTER(ctypes.c_int))

    dll.GetData.restype = int

    dll.GetData(option, 
                ptr_to_buf, 
                BUFSIZE, 
                ctypes.byref(actualLength))

    return (buf, actualLength.value)
GetData()
的调用是否准确地反映了.argtype

  • 可以像我在这里做的那样,将
    ptr\u作为
    ctypes.c\u char\u p
    传递给\u buf
  • 可以像我在这里做的那样将
    ctypes.byref
    传递到
    ctypes.POINTER
    中吗
  • 什么时候需要使用
    .pointer
    而不是
    .byref?
    我读过ctype文档,我知道他们说
    .byref
    更快,但我不清楚什么时候需要
    .pointer
  • 还有什么我做错的吗

  • .argtypes
    可以。您可能希望
    POINTER(c_ubyte)
    与原型完全一致,但通常
    c_char\p
    更易于使用

  • 可以像我在这里做的那样将ptr_作为ctypes.c_char_p传递给_buf吗
  • 对。数组作为相同元素类型的指针传递

  • 可以像我在这里所做的那样将ctypes.byref传递给ctypes.POINTER吗
  • 什么时候需要使用.pointer而不是.byref?我确实读过ctype文档,我知道他们说。byref更快,但我不清楚何时需要。指针
  • 当你需要一个具体的指针时,创建一个
    指针。我很少使用
    指针
    。假设您使用C语言编写了这段代码,并且有理由模仿它:

    intx=5;
    int*y=&x;
    
    Python的等价物是:

    x=c_int(5)
    y=指针(x)
    
  • 还有什么我做错的吗

  • .restype
    应具有
    ctype
    类型
    .restype=c_int
    是正确的。

    这一切都很好。使用
    c\u void\u p
    而不是
    c\u char\u p
    可能会更自然,但最终效果应该是一样的,所以我不会碰它。