您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

在Python中包装C库:C,Cython或ctypes?

在Python中包装C库:C,Cython或ctypes?

ctypes快速完成任务的最佳选择,并且在仍在编写Python的情况下很高兴与您合作!

我最近包装了一个FTDI驱动程序,用于使用ctypes与USB芯片进行通信,这很棒。我完成了所有工作,并在不到一个工作日的时间内完成了工作。(我只实现了我们需要的功能,大约有15个功能)。

出于同一目的,我们以前使用的是第三方模块PyUSB。PyUSB是实际的C / Python扩展模块。但是PyUSB在阻止读写时并没有释放GIL,这给我们带来了麻烦。因此,我使用ctypes编写了自己的模块,该模块在调用本机函数时会释放GIL。

需要注意的一件事是,ctypes不会知道#define所使用的库中的常量和内容,而只会知道函数,因此您必须在自己的代码中重新定义这些常量。

这是一个代码最终的外观示例(大量内容删除,只是试图向您展示其要旨):

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

有人对各种选项做了一些基准测试

如果不得不包装带有许多类/模板/等的C ++库,我可能会更加犹豫。但是ctypes可以很好地与结构配合使用,甚至可以回调到Python中。

python 2022/1/1 18:27:46 有331人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶