2015-11-04 51 views
0

我会被它的DLL到光谱仪连接,功能一个被定义为如何使用ctypes的无效**指针在python3

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

从文件,dev为指定光谱仪 手柄是该指数返回光谱仪的句柄指针 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

根据你的错误输出:

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

你忘了把​​c_void_p之前,这样的:

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

根据你的函数签名,手柄参数是指向一个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,它究竟是什么类型,等等)的准确等待时间。

+0

结果类型属性是'restype',而不是'restypes'。默认值是'c_int'。 – eryksun

+0

精心设计的ctypes包装应该会让翻译错误变得非常困难。应该事先捕获无效的参数以引发异常。为了更强的类型安全性,你可以创建一个句柄类型为'class Handle(ctypes.Structure):_fields_ = [('value',ctypes.c_void_p)]'。在'spectrometerOpen.argtypes'中设置'ctypes.POINTER(Handle)'。对于使用句柄的函数,只需在'argtypes'中设置'Handle'。如果使用无效参数调用函数,这将比使用'c_void_p'少得多。 – eryksun