简体   繁体   English

如何从 C function 签名中确定 Python3 ctypes.argtypes?

[英]How to determine Python3 ctypes .argtypes from C function signature?

I'm writing a ctypes interface to a 3rd party DLL (I have no control over the DLL).我正在为第 3 方 DLL 编写 ctypes 接口(我无法控制 DLL)。

My code seems to work, but I fear I'm setting up .argtypes wrong.我的代码似乎有效,但我担心我设置.argtypes错误。

The signature of the C function I'm trying to call is:我试图调用的 C function 的签名是:

int GetData(unsigned short option, unsigned char* buffer, int bufferLength, int &actualLength);

option indicates the kind of data requested, buffer points to a buffer I supply, bufferLength is the length of the buffer in bytes. option指示请求的数据类型, buffer指向我提供的缓冲区, bufferLength是缓冲区的长度(以字节为单位)。

The DLL function writes into the buffer, and puts the number of bytes it actually wrote into actualLength . DLL function 写入缓冲区,并将它实际写入的字节数放入actualLength

My code:我的代码:

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)

Does the call to GetData() accurately reflect the.argtypes?GetData()的调用是否准确反映了 .argtypes?

  1. Is it OK to pass ptr_to_buf as a ctypes.c_char_p as I'm doing here?可以像我在这里做的那样将ptr_to_buf作为ctypes.c_char_p传递吗?
  2. Is it OK to pass a ctypes.byref into a ctypes.POINTER as I'm doing here?可以像我在这里做的那样将ctypes.POINTER传递给ctypes.byref吗?
  3. When would be it be necessary to use .pointer instead of .byref?什么时候需要使用.pointer而不是.byref? I did read the ctype docs, I know they say .byref is faster, but I'm not clear on when .pointer is needed.我确实阅读了 ctype 文档,我知道他们说.byref更快,但我不清楚何时需要.pointer
  4. Is there anything else I'm doing wrong here?还有什么我做错了吗?

.argtypes is fine. .argtypes很好。 You may want POINTER(c_ubyte) to completely agree with the prototype, but often c_char_p is easier to work with.可能希望POINTER(c_ubyte)完全同意原型,但c_char_p通常更易于使用。

  1. Is it OK to pass ptr_to_buf as a ctypes.c_char_p as I'm doing here?可以像我在这里做的那样将 ptr_to_buf 作为 ctypes.c_char_p 传递吗?

Yes.是的。 An array is passed as a pointer of the same element type.数组作为相同元素类型的指针传递。

  1. Is it OK to pass a ctypes.byref into a ctypes.POINTER as I'm doing here?可以像我在这里做的那样将 ctypes.byref 传递给 ctypes.POINTER 吗?

Yes.是的。

  1. When would be it be necessary to use.pointer instead of.byref?什么时候需要使用.pointer 而不是.byref? I did read the ctype docs, I know they say.byref is faster, but I'm not clear on when.pointer is needed.我确实阅读了 ctype 文档,我知道他们说.byref 更快,但我不清楚何时需要.pointer。

Create a pointer when you need a concrete pointer.当你需要一个具体的指针时创建一个pointer I've rarely used pointer .我很少使用pointer Say you had this code in C and had some reason to mimic it:假设您在 C 中有此代码,并且有一些理由模仿它:

int x = 5;
int* y = &x;

The Python equivalent would be: Python 等效项为:

x = c_int(5)
y = pointer(x)
  1. Is there anything else I'm doing wrong here?还有什么我做错了吗?

.restype should have a ctype type. .restype应该有一个ctype类型。 .restype = c_int would be correct. .restype = c_int是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM