使用Cython和C++的项目组织

cls*_*udt 10 c++ python build cython

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

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

我想象一个源文件的目录结构,以及Cython的一些构建目录.

Project/
    src/
        *.h
        *.cpp
    cython/
        Project.pyx
        setup.py
Run Code Online (Sandbox Code Playgroud)

Gau*_*lio 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版本 - 继承自object- 给定类和引用计数管理,通过Py_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
Run Code Online (Sandbox Code Playgroud)

这里有一个例子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=[]
              )
    ]
)                   
Run Code Online (Sandbox Code Playgroud)

最后,主要的.pyx,将所有手写.pyx的cython部分连接在一起[ cyproject.pyx]:

include "pyext/Utils.pyx" 
include "pyext/TCLAP.pyx" 
include "pyext/LabSimulatorBase.pyx"
include "pyext/LabBinding.pyx"
include "pyext/LabSimulatorTime.pyx"
...
Run Code Online (Sandbox Code Playgroud)

注意:Cython生成的所有文件都保留在此setup文件夹中,与预期的手写内容(adapterspyext)完全分开.

在3.使用一个单独的DEPENDENCIES文件夹允许保持良好的分离(如果我将移动CYPROJECT- 及其依赖 - 在其他一些环境中).

所有这些都为您提供了如何组织这类项目的概述(我希望是一个相关的概述).