【问题标题】:ctypes dll declaration of variablesctypes dll变量声明
【发布时间】:2021-11-20 20:35:19
【问题描述】:

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

C 代码的文档如下,


/* global variables */

int main ()

char sDeviceSerialNumber[32];

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

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

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\3.1_ObidRFID_test\OBID_RFID_06.py", line 265, in <module>
    data = RFID.FEUSB_GetScanListPara(i, b"Device-ID")

  File "C:\xxxxx\3.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)

【问题讨论】:

    标签: python c dll ctypes


    【解决方案1】:

    您对.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 对应于一个字节字符串,因此使用b'DeviceID' 表示cPara。此外,如果您必须分配缓冲区,则第三个参数不太可能是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 原型。

    【讨论】:

    • @name_not_available 我只是在猜测,没有看到您尝试调用的函数的 C 原型。如果您创建一个minimal reproducible example 会产生错误,这将非常有帮助。它还可以帮助以 C 作为正确使用的示例制作一个工作版本,然后将其移植到 Python。第一步是让.argtypes.restype匹配你正在调用的函数,然后wrong type表示正确传递参数是问题。
    • st.com/resource/en/application_note/…。我正在尝试在上述文档第 17 页调用该函数。
    • @name_not_available 您应该使用原型和 C 示例编辑您的问题,但是从文档链接中我的猜测是正确的,您需要上面的代码。显示重现问题的确切代码(编辑问题)。你知道cValue.value 需要读取返回的字符串吗?我根据链接编辑了我认为您需要的答案。
    • 它有效....非常感谢!!
    • @name_not_available 太好了!一定要投票并选择正确的答案,然后?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 2012-06-15
    • 2014-11-09
    • 2021-12-16
    相关资源
    最近更新 更多