我在编译不同包中的cdef-ed类型时遇到问题,我在cython文档中找不到解释。
我在python src树的根目录中有这个setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [
Extension("flink.pytk.defs.FragIdx",
sources = ["flink/pytk/defs/FragIdx.pyx"]),
Extension("flink.pytk.fragments.STK_idx",
sources = ["flink/pytk/fragments/STK_idx.pyx"])
]
)
FragIdx是一个cdef-ed类型,在flink / pytk / defs / FragIdx.pyx中定义:
cdef class FragIdx:
cdef public FragIdx parent
cdef public FragIdx root
cdef public tuple label
...
STK_idx是FragIdx的扩展,在flink / pytk / fragments / STK_idx.pyx中定义:
from flink.pytk.defs.FragIdx import FragIdx
cdef class STK_idx(FragIdx):
...
当我尝试使用帖子开头列出的setup.py进行编译时,FragIdx编译得很好,但是当涉及到STK_idx时,我收到以下错误消息:
flink/pytk/fragments/STK_idx.pyx:5:5: 'FragIdx' is not a type name
请注意,源树的根目录列在$ PYTHONPATH。
中如果有人能对此有所了解,我将非常感激,非常感谢!
丹尼尔
答案 0 :(得分:10)
哦,好吧,对于那些有类似问题的人,看起来好像我找到了答案。
我希望python能够自动扫描编译到共享库FragIdx.so中的符号,而看起来这个信息必须显式地提供为.pxd文件(在运行Cython之后它成为C头文件)。 / p>
该过程基本上涉及两个步骤:
.pxd
)文件; cimport
(而不是import
)导入超类定义。所以,为了使它更通用。
假设您已在模块A
中定义了cdef-ed类型pkg1.mod1
。然后,您在B
子类pkg2.mod2
中设置类型A
。
您的目录结构如下所示:
pkg1/
mod1.pyx
mod1.pxd
pkg2/
mod2.pyx
mod2.pxd
在pkg1/mod1.pxd
中你会有,比如说:
cdef class A:
cdef int a
cdef int b
在pkg1/mod1.pyx
中你会提供你班级的方法。
在pkg2/mod2.pxd
中,您将拥有:
from pkg1.mod1 cimport A #note "cimport"!!
cdef class B(A):
cdef ... # your attributes here
同样,在pkg2/mod2.pyx
中,您必须再次cimport
A符号:
from pkg1.mod1 cimport A #note "cimport"!!
cdef class B(A):
... # your methods here
有趣的是,如果您只想在python代码中使用A
,而不是使用它来定义子类型,则不需要定义文件mod1.pxd
。这与以下事实有关:在创建扩展类型时,您需要为C编译器提供定义,而在运行python代码时没有这个问题,但由于它不是非常直观,因此重要的是指出它进行。
这些信息实际上可以在Cython docs中找到,但也许可能更明确一些。
希望这些信息可以为某些人节省一些。