0

我正在尝试使用 d2xx.dll,它是一个用于连接 FTDI 的 USB 控制器芯片的库。我想在我的 python 代码中使用这个库。我决定在 python 中使用 ctypes 库来调用 dll 函数。我未能从 dll 文件中适当地调用函数,并且我认为我在传递给 dll 库中的函数的变量类型方面存在一些问题。我不是专业程序员,所以请放轻松。:D

这是迄今为止尝试过的,

import ctypes
from ctypes import *

d2xxdll = ctypes.cdll.LoadLibrary('ftd2xx.dll') #Load the dll library 
d2xxdll.FT_CreateDeviceInfoList.argtypes =[ctypes. c_ulong] # specify function's input type
d2xxdll.FT_CreateDeviceInfoList.restype = ctypes.c_ulong # specify function's return type

numDevs = ctypes.c_ulong()
p_numDevs = POINTER(numDevs)
FT_STATUS = d2xxdll.FT_CreateDeviceInfoList(p_numDevs)

print(FT_STATUS)
print(numDevs)

我只是想检测有多少 D2XX 设备与 FT_CreateDeviceInfoList() 函数连接。FT_CreateDeviceInfoList 在d2xx.dll 文档第 6 页中进行了描述。该函数有一个输入参数,它是一个指向无符号长整数的指针,它返回 USB 设备的状态。我用“numDevs = ctypes.c_ulong()”声明了一个无符号长整数,并在“p_numDevs = POINTER(numDevs)”中声明了它的指针,当我运行代码时出现以下错误。

Traceback (most recent call last):
  File "C:\Users\asus\Desktop\dokümanlar\Python_Ogren\Ctypes_cll\d2xx_dll.py", line 9, in <module>
    p_numDevs = ctypes.POINTER(numDevs)
TypeError: must be a ctypes type

我还尝试使用 byref 来传递 numDevs 的地址:

import ctypes
from ctypes import *

d2xxdll = ctypes.cdll.LoadLibrary('ftd2xx.dll') #Load the dll library 
d2xxdll.FT_CreateDeviceInfoList.argtypes =[ctypes. c_ulong] # specify function's input type
d2xxdll.FT_CreateDeviceInfoList.restype = ctypes.c_ulong # specify function's return type

numDevs = ctypes.c_ulong()

FT_STATUS = d2xxdll.FT_CreateDeviceInfoList(ctypes.byref(numDevs))

print(FT_STATUS)
print(numDevs)


这次我得到以下信息:

Traceback (most recent call last):
  File "C:\Users\asus\Desktop\dokümanlar\Python_Ogren\Ctypes_cll\d2xx_dll.py", line 10, in <module>
    FT_STATUS = d2xxdll.FT_CreateDeviceInfoList(ctypes.byref(numDevs))
ArgumentError: argument 1: <type 'exceptions.TypeError'>: wrong type

我应该如何传递输入参数?我知道python中有一些d2xx.dll的包装器,比如pyusb,但由于某种原因,我无法让它们工作。我用 d2xx.dll 编写了一些 C 代码,它们的工作方式非常有魅力。现在我正在寻找一种让他们在 python 中工作的方法。

提前致谢。

4

1 回答 1

0

该函数的C定义是:

typedef ULONG   FT_STATUS;

FTD2XX_API
FT_STATUS WINAPI FT_CreateDeviceInfoList(
    LPDWORD lpdwNumDevs
);

ctypes有一个 Windows 类型库,可帮助您正确映射它们。参数类型不是 ac_ulong而是 a POINTER(c_ulong)。该wintypes模块LPDWORD正确定义为这种类型。然后你创建一个DWORD并传递它byref()

下面是一个完整的包装:

import ctypes
from ctypes import wintypes

FT_STATUS = wintypes.ULONG
FT_OK = 0

# Note: WINAPI is __stdcall so if using 32-bit Windows you want WinDLL().
#       Use CDLL() for __cdecl calling convention.
#       On 64-bit Windows there is only one calling convention and either works.
ftd2xx = ctypes.WinDLL('ftd2xx')

_FT_CreateDeviceInfoList = ftd2xx.FT_CreateDeviceInfoList
_FT_CreateDeviceInfoList.argtypes = wintypes.LPDWORD,
_FT_CreateDeviceInfoList.restype = FT_STATUS

def FT_CreateDeviceInfoList():
    num_devs = wintypes.DWORD()
    if _FT_CreateDeviceInfoList(ctypes.byref(num_devs)) != FT_OK:
        raise RuntimeError('failed')
    return num_devs.value
于 2020-02-13T17:34:24.383 回答