如何使用Cython将C结构体暴露给Python且支持包内外调用?
问题解决:Cython暴露C语言Point结构体给Python调用
问题根因
- 你在
blob.pxd中声明的cdef extern struct Point是C层面的类型,仅支持被其他Cython代码(.pxd/.pyx文件)通过cimport调用,不会自动暴露到Python模块的公开属性中 - 你的
blob.pyx是空文件,没有做任何Python层面的类型封装,因此Python导入模块后自然找不到Point属性
实现方案
你的需求需要同时满足两类调用场景,按如下步骤修改即可:
1. 保留原有pxd声明(支持包内Cython文件调用)
你现有blob.pxd的内容不需要修改,包内其他Cython文件可直接通过cimport blob的方式使用C级别的Point结构体,无额外性能开销。
2. 修改blob.pyx添加Python层包装类(支持纯Python代码调用)
在空的blob.pyx中添加如下代码,将C结构体包装为Python可访问的扩展类型:
# blob.pyx cimport blob # 导入同模块pxd中声明的C级Point结构体 # 定义Python可见的扩展类型 cdef class Point: # 存储底层C结构体实例 cdef blob.Point _c_point # 对外暴露的初始化方法 def __init__(self, double x=0.0, double y=0.0): self._c_point.x = x self._c_point.y = y # 暴露x属性给Python读写 @property def x(self): return self._c_point.x @x.setter def x(self, double val): self._c_point.x = val # 暴露y属性给Python读写 @property def y(self): return self._c_point.y @y.setter def y(self, double val): self._c_point.y = val # 可选:添加打印方法方便调试 def __repr__(self): return f"Point(x={self.x}, y={self.y})"
3. 重新编译验证
使用原有编译命令重新生成扩展模块:python setup.py build_ext --inplace
纯Python侧调用测试:
import blob p = blob.Point(1.2, 3.4) print(p) # 输出 Point(x=1.2, y=3.4) print(p.x, p.y) # 输出 1.2 3.4 p.x = 5.6 print(p.x) # 输出 5.6
包内Cython文件调用测试:
# 包内其他pyx文件,比如utils.pyx cimport blob # 直接使用零开销的C级Point结构体 cdef blob.Point c_p c_p.x = 2.0 c_p.y = 4.0
内容的提问来源于stack exchange,提问作者Aaron Stanek
相关产品推荐
相关产品推荐

