Python从小白到高手实现系列四百二十七:CFFI

本文介绍了Python的外部函数接口CFFI,它是ctypes的替代品,更强调重用纯C代码。通过使用CFFI重新实现快速排序示例,展示了与ctypes的区别。还讨论了构建Python扩展的多种方式,如纯C扩展、Cython等,并建议使用合适工具提高代码可读性与可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CFFI 是Python 的外部函数接口,是ctypes 的一个替代品。它不是标准库的一部分,
但是它作为一个cffi 包,可以很容易地从PyPI 上获得。它不同于ctypes,因为它更加强调重用纯C 代码,而不是在单个模块中提供大量的Python API。它的方式更复杂,并且
还有一个特性,它允许你使用C 编译器将集成层的某些部分自动编译为扩展。因此,它可
以用作填补C 扩展和ctypes 之间差距的混合解决方案。
因为它是一个非常大的项目,不可能用很少的段落就能快速地介绍它。另一方面,不
多说一些关于它的使用是一件非常遗憾的事情。我们已经讨论了使用ctypes 从标准库集
成qsort()函数的一个示例。因此,显示这两个解决方案之间的主要区别的最好方法是使
用cffi 重新实现相同的示例。而我希望,一段代码胜过千言万语,如下所示:
from random import shuffle
from cffi import FFI
ffi = FFI()
ffi.cdef(“”"
void qsort(void *base, size_t nel, size_t width,
int (*compar)(const void , const void ));
“”")
C = ffi.dlopen(None)
@ffi.callback("int(void
, void
)")
def cffi_int_compare(a, b):

回调签名需要类型的精确匹配,

这涉及到比ctypes 更少的魔法,

但需要更详细,更明确的转型。

int_a = ffi.cast(‘int*’, a)[0]
int_b = ffi.cast(‘int*’, b)[0]
print(" %s cmp %s" % (int_a, int_b))

根据快速排序的规范,应该这样返回::

* 如果a 小于b,则小于0

* 如果a 等于b,则等于0

* 如果a 大于b,则大于0

return int_a - int_b
def main():
numbers = list(range(5))
shuffle(numbers)
print("shuffled: ", numbers)
c_array = ffi.new(“int[]”, numbers)
C.qsort(

指向被排序的数组的指针

c_array,

数组的长度

len(c_array),

数组中单个元素的大小

ffi.sizeof(‘int’),

回调(指向C 比较函数的指针)

cffi_int_compare,
)
print("sorted: ", list(c_array))
if name == “main”:
main()
小结
本章解释了本书中最高级的一个主题。我们讨论了构建Python 扩展的原因和工具。我
们从编写纯C 扩展开始,这些扩展仅依赖于Python/C API,然后使用Cython 重新实现它们,
用以说明选择合适的工具,构建扩展是如此的容易。
还有一些原因,以艰难的方式构建扩展,只使用纯C 编译器和Python.h 头文件。总
之,最好的建议是使用工具,如Cython 或Pyrex(这里不是推荐),因为它可以提高代码库
的可读性与可维护性。它还将为你节省由于不当的引用计数和内存管理导致的大多数问题。
我们对扩展的讨论以ctypes 和CFFI 的介绍结束,它们可以作为解决集成共享库问
题的另一种方法。因为他们不需要在编写自定义扩展时从编译的二进制文件中调用函数,
它们应该是你选择的工具,特别是如果你不需要使用自定义C 代码。
在下一章中,我们将从低级编程技术中休息一段时间,然后深入探讨同样重要的主题
即代码管理和版本控制系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

断水流大撕兄

你的鼓励,就是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值