10

我想为我的 C++ 项目提供一个 Python 接口。从技术上讲,我决定使用 Cython 来包装 C++ 代码。随着时间的推移,整个项目旨在成为一个 Python 扩展模块,但起初,这是高度实验性的。逐渐地,C++ 类需要暴露给 Python。

我的问题是如何最好地组织文件和构建配置,以便 Cython 生成的和人工编写的 C++ 代码不会混合在一起,并且 Python 扩展模块与其他目标完全分开构建。

我想像这样的源文件目录结构,以及 Cython 的一些构建目录。

Project/
    src/
        *.h
        *.cpp
    cython/
        Project.pyx
        setup.py
4

1 回答 1

5

基本上我有3个文件夹:

  1. CPROJECT, C++ 库:生成libcproject.so共享对象
  2. CYPROJECT, cythonized Python 扩展:cyproject.so使用 Cython 生成
  3. DEPENDENCIES,依赖关系:我复制两个项目的外部需求

在 1.我构建了 C++ 扩展(使用 gcc --shared编译-fPIC选项编译),它将向 python 公开并且CYPROJECT依赖于向 Python 公开功能。作为后处理命令,结果.so被复制到DEPENDENCIES/libcproject/(以及include文件)中。这样,库当然也可以在纯 C++ 项目中独立使用。

在 2.我使用 3 个子文件夹:

  • adapters: 主要包含 C++ 附加类(通常是从 提供的类派生的类libcproject.so)。这些通常是通过特定于 Cython 要求的功能增强的类(例如存储给定类PyObject *的目标 Python 版本的 C 版本 - 继承自- 和引用计数管理,通过和...)。objectPy_XINCREFPy_DECREF
  • pyext:所有 Cython 手写.pyx文件都存储在哪里。
  • setup: 包含setup.sh脚本(用于设置依赖路径并调用python setup.py build_ext --inplace用于生成最终文件cyproject.so(将添加到PYTHONPATH)和cyproject.pyx.

那么setup子文件夹中有什么?

这是一个示例代码setup.sh

export PYTHONPATH=$PYTHONPATH:../../../DEPENDENCIES/Cython-0.18
export PATH=$PATH:../../../DEPENDENCIES/libcproject:../../../DEPENDENCIES/Cython-0.18/bin

# Note the `../../../DEPENDENCIES/libcproject`...

CC="gcc"   \
CXX="g++"   \
    python setup.py build_ext --inplace

这里有一个例子setup.py(主要是为了演示如何adapters编译附加的):

import sys
import os
import shutil

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

# Cleaning
for root, dirs, files in os.walk(".", topdown=False):
    for name in files:
        if (name.startswith("cyproject") and not(name.endswith(".pyx"))):
            os.remove(os.path.join(root, name))
    for name in dirs:
        if (name == "build"):
            shutil.rmtree(name)

# Building
setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [
    Extension("cyproject", 
              sources=["cyproject.pyx", \
                       "adapter/ALabSimulatorBase.cpp", \
                       "adapter/ALabSimulatorTime.cpp", \
                       "adapter/ALabNetBinding.cpp", \
                       "adapter/AValueArg.cpp", \
                       "adapter/ALabSiteSetsManager.cpp", \
                       "adapter/ALabSite.cpp", \
                       ],
              libraries=["cproject"],
              language="c++",
              extra_compile_args=["-I../inc", "-I../../../DEPENDENCIES/python2.7/inc", "-I../../../DEPENDENCIES/gsl-1.8/include"], 
              extra_link_args=["-L../lib"]
              extra_compile_args=["-fopenmp", "-O3"],
              extra_link_args=[]
              )
    ]
)                   

最后是 main ,它将cython 部分的.pyx所有手写 s 链接在一起 [ ] :.pyxcyproject.pyx

include "pyext/Utils.pyx" 
include "pyext/TCLAP.pyx" 
include "pyext/LabSimulatorBase.pyx"
include "pyext/LabBinding.pyx"
include "pyext/LabSimulatorTime.pyx"
...

注意:Cython 生成的所有文件都保留在此setup文件夹中,与手写的东西(adapterspyext)很好地分开,正如预期的那样。

3.使用分离的DEPENDENCIES文件夹可以很好地分离(以防我将CYPROJECT- 及其依赖项 - 在其他环境中移动)。

所有这些都是为了给你一个关于如何组织这类项目的概述(我希望是相关的)。

于 2013-05-29T05:39:01.250 回答