ctypes dll变量声明

ctypes dll declaration of variables

我正在尝试将以下函数与 ctypes 一起使用,但我确实遇到了如何正确声明所有参数和变量的问题。

C代码的文档如下,


/* global variables */

int main ()

char sDeviceSerialNumber[32];

FEUSB_GetScanListPara( 0, "Device-ID", sDeviceSerialNumber ) ;

sDeviceSerialNumber 应该是我在 Python 中需要进一步使用的函数的 return 值。

Python代码:

def FEUSB_GetScanListPara(iIndex, cPara):
    libfeusb.FEUSB_GetScanListPara.argtypes = [ctypes.c_int, 
                                               ctypes.c_wchar_p,                                                  
                                    ctypes.POINTER(ctypes.c_char_p)
                                              ]
  
    libfeusb.FEUSB_GetScanListPara.restype = ctypes.c_int
    
    iIndex = ctypes.c_int(iIndex)
    cValue_buffer = ctypes.create_string_buffer(32)
    cValue = ctypes.c_char_p(ctypes.addressof(cValue_buffer))

    value = libfeusb.FEUSB_GetScanListPara(iIndex, 
                                           cPara,                                      
                                           ctypes.byref(cValue)
                                           )

if __name__ == "__main__":
   i = 0
   RFID.FEUSB_GetScanListPara(i, "Device-ID")

当我用上面的代码调用函数时,我得到一个错误代码,FEUSB_ERR_UNKNOWN_PARAMETER,因此我假设我没有正确声明参数。

欢迎任何意见!

编辑 1

    def FEUSB_GetScanListPara(iIndex, cPara):
        libfeusb.FEUSB_GetScanListPara.argtypes = [ctypes.c_int, 
                                                   ctypes.c_char_p,
                                                   ctypes.c_char_p
                                                
                                                  ]
        libfeusb.FEUSB_GetScanListPara.restype = ctypes.c_int  
        cValue = ctypes.create_string_buffer(32)
        value = libfeusb.FEUSB_GetScanListPara(iIndex, cPara, 
                                               ctypes.byref(cValue))

        print("1.0", cPara, "back value", " = ", value)
        print("1.1", cPara, " = ", cValue.value)

        print("######")

if __name__ == "__main__":

   data = RFID.FEUSB_GetScanListPara(i, b"Device-ID")

Python 控制台:


FEUSB_ClearScanList =  0
FEUSB_Scan =  0
FEUSB_GetScanListSize =  1
Traceback (most recent call last):

  File "C:\xxxxx.1_ObidRFID_test\OBID_RFID_06.py", line 265, in <module>
    data = RFID.FEUSB_GetScanListPara(i, b"Device-ID")

  File "C:\xxxxx.1_ObidRFID_test\OBID_RFID_06.py", line 89, in FEUSB_GetScanListPara
    value = libfeusb.FEUSB_GetScanListPara(iIndex, cPara, ctypes.byref(cValue))

ArgumentError: argument 3: <class 'TypeError'>: wrong type

编辑 2

工作代码


    def FEUSB_GetScanListPara(iIndex, cPara):
        libfeusb.FEUSB_GetScanListPara.argtypes = [ctypes.c_int, 
                                                   ctypes.c_char_p,
                                                   ctypes.c_char_p
                                                   ]
                                                
        libfeusb.FEUSB_GetScanListPara.restype = ctypes.c_int                                          
        cValue = ctypes.create_string_buffer(32)
        
        return_value = libfeusb.FEUSB_GetScanListPara(0, b'Device-ID', 
                                                      cValue)

您对 .argtypes 的声明将匹配以下的 C 原型:

int FEUSB_GetScanListPara(int, wchar_t*, char**)

您没有提供确切的 C 原型,但是从您的示例中可以看出:

FEUSB_GetScanListPara( 0, "Device-ID", sDeviceSerialNumber ) ;

并且知道 wchar_t* 不是通用接口参数,您实际上可能有简单的 char* 声明,例如:

int FEUSB_GetScanListPara(int, const char*, char*);

我假设第二个参数是输入参数,第三个参数是输出参数。请注意,c_char_p 对应于一个字节字符串,因此对 cPara 使用 b'DeviceID'。此外,如果您必须分配缓冲区,则第 3 个参数不太可能是 char**。如果 API 本身不返回指针,而是填充已分配的缓冲区,则 char*ctypes.c_char_p 是合适的。您正确使用 create_string_buffer() 作为输出参数。

请注意,您不需要将 iIndex 包裹在 c_int 中。从 .argtypesctypes 知道第一个参数是 c_int 并为您转换它。如果未提供 .argtypes,这也是默认设置,但最好明确并提供 .argtypes.

此代码应该有效。我没有要验证的 DLL:

import ctypes as ct

libfeusb = CDLL('./FESUB') # assuming in same directory
libfeusb.FEUSB_GetScanListPara.argtypes = ct.c_int, ct.c_char_p, ct.c_char_p
libfeusb.FEUSB_GetScanListPara.restype = ct.c_int
cValue = ct.create_string_buffer(32)
ret = libfeusb.FEUSB_GetScanListPara(0, b'Device-ID', cValue)
if ret == 0:
    print(cValue.value)
else:
    print('error:',ret)

如果您仍有问题,请使用 minimal, reproducible example 编辑您的问题。请务必提供真实的 C 原型。