22

我在这里找到了文档、邮件列表和这个问题之间的部分答案,但我想得到一个更直接的答案来解决我的具体问题......

我正在通过尝试一点一点地包装我已经在使用的库的小部分来学习 cython,该库目前包装在 boost::python 中。我为这个 boost 包装器贡献了一点点,并将它用作 c++ 参考,同时我使用ZeroMQ Python 绑定作为 cython 参考。

我的问题是关于项目结构的。这个 lib 的当前 boost 版本编译为单个.so,这就是我的目标。我很快发现你不能直接将多个.pyx模块编译成一个.so. 然后我开始沿着cppclass在文件中定义 's的路线pxd,以及它们相应的 python 导出的实现类 in .pxi,并试图将它们包含到单个文件pyx中以进行编译。pxi虽然它一开始是有效的,但当我再写一点时,由于包含在不同的地方,我遇到了多个定义冲突的问题。

我很想听到解决以下问题和目标的适当组织方法:

  • 将公共类命名为与cppclass(我现在通过将 cppclass 命名为不同的名称pyd并使用导入的命名空间来处理相似的名称来执行此操作,ala使用 cimport 来解决命名冲突
  • 单一.so作为编译输出(可接受的方法?
  • 我是否将pyx多包含方法pyx单独用于主要内容,或者该主要内容是否应该pyx包含除包含包含之外的任何其他内容?
  • 在哪里集中定义将在 python 中导出的常量?
  • 有首选的文件夹结构吗?现在,src我的setup.py. 看到这么多pxi, pxd, pyx文件会让人感到困惑。
  • pxi现在完全没有必要了吗?如果没有,我是否需要使用 cython 样式的 ifndef 保护来处理不同模块之间的多个包含?
  • 我知道 ZeroMQ python 绑定构建多个模块并通过将它们包含在__init__.py. 这真的是 cython 的正确方法吗?

作为参考,我正在练习重新包装的项目是PyOpenNI (openni)。这个 boost 项目采用的模式是将公共对象收集到一个位置,然后与源定义一个 1 对 1 的标头定义,然后有一个巨大的包装器将所有定义收集到一个位置。以及添加的自定义异常处理和实用程序。

4

2 回答 2

22

在等待一个明确的答案时,我一直在组织我的代码。到目前为止,将pyx文件包含在单个文件pyx中进行编译一直在工作。

setup.py的很简单,例如:

ext_modules = [
    Extension(
        "openni", 
        ["src/openni.pyx"], 
        language="c++",
        include_dirs=['src/', '/usr/include/ni'],
        libraries=['OpenNI'],
    )
],

主要openni.pyx看起来像:

include "constants.pyx"
include "exceptions.pyx"
include "context.pyx"
...

我有一个共同点libopenni.pxd,可以为其余模块提供仅声明的外部。

我将cppclass声明命名为与类定义不同pxd的名称pyx以避免名称冲突:

xncontext.pxd

cdef extern from "XnCppWrapper.h" namespace "xn":
    cdef cppclass Context:
           ...

上下文.pyx:

from libopenni cimport *
from xncontext cimport Context as c_Context 

cdef class Context:
    cdef c_Context *handle   
        ...
于 2012-08-03T22:15:33.307 回答
0

回答是否有首选的文件夹结构?

.pyx是的,Cython和文件的首选文件夹结构是.pxd像对待文件一样对待它们.py:每个模块一个,采用组织良好的包结构。__init__.pxd可以像提供文件一样提供__init__.py文件来组装一组精选符号,以从其子模块/包中收集一组精选符号以进行 cimporting。

没错,这会.so为每个模块生成一个文件,但这些文件隐藏在构建目录中。Python 的构建模块也是如此。每一个都有一个对应的.so文件。这是一个问题吗?

于 2016-08-24T17:06:18.350 回答