如何在Cython中封装外部C++库的自定义Ciphertext类型?
Cython封装Palisade自定义类型方案
基础封装实现
你不需要在pxd中声明私有成员m_ciphertext,Cython只需要识别你需要调用的公开接口,私有成员不会被Cython访问,无需定义。针对外部库的自定义类型,做不透明声明即可,完整的pxd写法参考:
# 先声明Palisade库的相关类型 cdef extern from "palisade.h" namespace "lbcrypto": # 不透明声明依赖的基础类型,不需要写内部结构 cdef cppclass DCRTPoly: pass # 声明模板类型Ciphertext cdef cppclass Ciphertext[T]: pass # 声明模板类型CiphertextImpl cdef cppclass CiphertextImpl[T]: pass # 声明你自己的包装类 cdef extern from "ckks_wrapper.h" namespace "pycrypto": cdef cppclass CiphertextInterfaceType: # 构造函数 CiphertextInterfaceType() except + # 接收Ciphertext参数的构造函数 CiphertextInterfaceType(Ciphertext[DCRTPoly]) except + # 析构函数 ~CiphertextInterfaceType() # Getter方法,返回常量引用 const CiphertextImpl[DCRTPoly]& GetCiphertext() const
追问解答
1. 头文件关联逻辑
你的理解不完全正确:
Cython不会自动查找palisade.h,你需要满足两个条件才能正常访问lbcrypto命名空间的类型:
- 要么在pxd中显式通过
cdef extern from "palisade.h"引入该头文件 - 要么你引入的
ckks_wrapper.h已经包含了palisade.h,同时你需要在setup.py的编译配置里把Palisade库的头文件路径加入include_dirs,否则编译阶段会报头文件找不到的错误。
只要头文件引用链条完整,Cython生成的C++代码就能正常识别lbcrypto命名空间下的所有类型。
2. 类型声明写法
你给出的两种写法都不正确,不需要嵌套extern from块,也不需要把Palisade的类型放在pycrypto命名空间的声明块里:
- 嵌套
extern from属于非法Cython语法,会直接触发编译错误 lbcrypto和pycrypto是平级的命名空间,分开声明即可,在同一个pxd文件内先声明的类型,后面可以直接引用,不会出现你担心的无法在CiphertextInterfaceType中使用的问题。
另外你代码里的cdef extern from "ckks_wrapper.cpp"是多余的,Cython封装只需要引入头文件,cpp文件在编译链接阶段处理即可。
内容的提问来源于stack exchange,提问作者IanQ
相关产品推荐
相关产品推荐

