使用Cython时如何传递C对象?报错Cannot convert Python object to class_name怎么办
问题背景
我准备了如下最小示例,其中C++类采用大写命名,Cython类采用小写命名。执行语句self.ip = new BCD(ob.ip[0].obj_abc)时收到报错Cannot convert Python object to 'ABC',但ip本身是class BCD的指针,且BCD类包含obj_abc成员。请问我该如何通过指针访问BCD中内置的obj_abc?
注:前三个定义存放在
.pxd文件中,最后一个定义存放在.pyx文件中。
cdef cppclass ABC: ABC() cdef cppclass BCD: ABC obj_abc BCD(ABC &) BCD() cdef class bcd: cdef BCD * ip cdef class bcd: def __cint__(self, ob=None): if ob is not None: self.ip = new BCD(ob.ip[0].obj_abc) # isinstance(ob, bcd) is True else: self.ip = new BCD()
解决方案
给__cint__方法的ob参数加上静态类型标注即可解决问题,将原定义行:def __cint__(self, ob=None):
修改为:def __cint__(self, bcd ob=None):
原理说明
未给ob加类型标注时,Cython会将其识别为通用Python对象,无法直接访问Cython扩展类bcd中用cdef声明的成员属性ip,访问ob.ip时会被当作Python属性查找,返回的是Python对象而非原生C指针指向的内容,后续取obj_abc时自然无法匹配C的ABC类型要求。加上bcd类型标注后,Cython会在编译阶段识别ob的静态类型,直接访问其原生C层级的ip成员,获取到正确的BCD指针,进而取出类型匹配的obj_abc成员传入构造函数。
内容的提问来源于stack exchange,提问作者Andrew Mathews
相关产品推荐
相关产品推荐

