如何在python3中使用ctypes void **指针

时间:2015-11-04 08:52:38

标签: python ctypes

我想用它的DLL连接一个光谱仪,其中一个函数被定义为

UINT UAI_SpectrometerOpen(unsigned int dev, void** handle, unsigned int VID,  unsigned int PID)

来自document,dev是指定光谱仪的索引 handle是返回光谱仪手柄的指针 VID是提供指定的VID PID是提供指定的PID dev,VID,PID是已知的,但我不知道如何设置句柄。 我目前的代码是

import ctypes
otoDLL = ctypes.CDLL('UserApplication.dll')
spectrometerOpen = otoDLL.UAI_SpectrometerOpen
spectrometerOpen.argtypes = (ctypes.c_uint, ctypes.POINTER(c_void_p),
                         ctypes.c_uint, ctypes.c_uint)
spectrometerOpen.restypes = ctypes.c_uint
handle = ctypes.c_void_p
errorCode = spectrometerOpen(0, handle, 1592, 2732)

当我运行上面的代码时,我收到错误

runfile('C:/Users/Steve/Documents/Python Scripts/otoDLL.py', wdir='C:/Users/Steve/Documents/Python Scripts')
Traceback (most recent call last):

  File "<ipython-input-1-73fe9922d732>", line 1, in <module>
    runfile('C:/Users/Steve/Documents/Python Scripts/otoDLL.py', wdir='C:/Users/Steve/Documents/Python Scripts')

  File "C:\Users\Steve\Anaconda3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 685, in runfile
    execfile(filename, namespace)

  File "C:\Users\Steve\Anaconda3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 85, in execfile
    exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)

  File "C:/Users/Steve/Documents/Python Scripts/otoDLL.py", line 5, in <module>
    spectrometerOpen.argtypes = (ctypes.c_uint, ctypes.POINTER(c_void_p),

NameError: name 'c_void_p' is not defined

我不熟悉ctypes和C,任何人都可以帮我解决这个问题。 非常感谢。

1 个答案:

答案 0 :(得分:1)

根据您的错误输出:

  File "C:/Users/Steve/Documents/Python Scripts/otoDLL.py", line 5, in <module>
    spectrometerOpen.argtypes = (ctypes.c_uint, ctypes.POINTER(c_void_p),

您忘记将ctypes放在c_void_p之前,因此:

spectrometerOpen.argtypes = (ctypes.c_uint, ctypes.POINTER(ctypes.c_void_p),
                         ctypes.c_uint, ctypes.c_uint)

根据你的函数签名,handle参数是一个指向void*的指针,因此你需要像这样传递它:

import ctypes
otoDLL = ctypes.CDLL('UserApplication.dll')
spectrometerOpen = otoDLL.UAI_SpectrometerOpen
spectrometerOpen.argtypes = (ctypes.c_uint, ctypes.POINTER(ctypes.c_void_p),
                         ctypes.c_uint, ctypes.c_uint)
spectrometerOpen.restypes = ctypes.c_uint

# declare HANDLE type, which is a void*
HANDLE = ctypes.c_void_p

# example: declare an instance of HANDLE, set to NULL (0)
my_handle = HANDLE(0)

#pass the handle by reference (works like passing a void**)
errorCode = spectrometerOpen(0, ctypes.byref(my_handle), 1592, 2732)

注意:这只是一个示例,您应该检查spectrometerOpen函数的文档,看看它究竟在等待handle参数究竟是什么(可以是NULL,它是什么类型的确切等等。)。