<p><code>ctypes</code>是您快速完成任务的最佳选择,在您仍在编写Python时与之合作是一种乐趣!</p>
<p>我最近包装了一个<a href="http://www.ftdichip.com/" rel="noreferrer">FTDI</a>驱动程序,用于使用ctypes与USB芯片通信,非常棒。我在不到一个工作日的时间里完成了所有的工作。(我只实现了我们需要的功能,大约15个功能)。</p>
<p>我们以前使用第三方模块<a href="http://bleyer.org/pyusb/" rel="noreferrer">PyUSB</a>也是为了同样的目的。PyUSB是一个实际的C/Python扩展模块。但是PyUSB在阻塞读写时并没有释放GIL,这给我们带来了问题。所以我使用ctypes编写了我们自己的模块,它在调用本机函数时释放GIL。</p>
<p>需要注意的一点是,ctypes不会知道您正在使用的库中的<code>#define</code>常量和内容,只知道函数,因此您必须在自己的代码中重新定义这些常量。</p>
<p>下面是一个代码的最终外观示例(很多代码被剪掉了,只是想向您展示它的要点):</p>
<pre><code>from ctypes import *
d2xx = WinDLL('ftd2xx')
OK = 0
INVALID_HANDLE = 1
DEVICE_NOT_FOUND = 2
DEVICE_NOT_OPENED = 3
...
def openEx(serial):
serial = create_string_buffer(serial)
handle = c_int()
if d2xx.FT_OpenEx(serial, OPEN_BY_SERIAL_NUMBER, byref(handle)) == OK:
return Handle(handle.value)
raise D2XXException
class Handle(object):
def __init__(self, handle):
self.handle = handle
...
def read(self, bytes):
buffer = create_string_buffer(bytes)
count = c_int()
if d2xx.FT_Read(self.handle, buffer, bytes, byref(count)) == OK:
return buffer.raw[:count.value]
raise D2XXException
def write(self, data):
buffer = create_string_buffer(data)
count = c_int()
bytes = len(data)
if d2xx.FT_Write(self.handle, buffer, bytes, byref(count)) == OK:
return count.value
raise D2XXException
</code></pre>
<p>有人做了各种选择。</p>
如果我不得不用大量的类/模板来包装C++库,我可能会更加犹豫,但是cType与结构非常好,甚至可以将{a4}导入到Python中。</p>