11

我在编译不同包中的 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 中列出。

如果有人能对此有所了解,我将不胜感激,非常感谢!

丹尼尔

4

1 回答 1

12

哦,好吧,对于那些有类似问题的人,看起来也许我找到了答案。

我期待 python 自动扫描编译到共享库 FragIdx.so 中的符号,而不是看起来必须以 .pxd 文件的形式显式提供此信息(在 Cython 运行后成为 C 头文件)。

该过程基本上涉及两个步骤:

  1. 为超类创建一个定义(.pxd)文件;
  2. cimport通过(而不是import)在子类模块中导入超类定义。

因此,使其更通用。

假设你已经A在 module中定义了你的 cdef-ed 类型pkg1.mod1B然后你在pkg2.mod2那个子类中cdef 一个类型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

有趣的是,如果您只想A在您的 python 代码中使用,而不是使用它来定义子类型,mod1.pxd则不需要定义文件。这与创建扩展类型时需要对 C 编译器可用的定义有关,而在运行 python 代码时没有这个问题,但由于它不是很直观,因此指出它可能很重要出去。

这些信息实际上可以在Cython 文档中找到,尽管它可能会更明确一点。

希望这些信息可以为某人节省一些。

于 2011-03-05T19:40:25.613 回答