我想为我的C ++项目提供Python接口。从技术上讲,我决定使用Cython来包装C ++代码。随着时间的推移,整个项目将成为一个Python扩展模块,但首先,这是高度实验性的。渐渐地,C ++类需要暴露给Python。
我的问题是如何最好地组织文件和构建配置,以便Cython生成的和人工编写的C ++代码不会混合,并且Python扩展模块与其他目标完全分开构建。
我想象一个源文件的目录结构,以及Cython的一些构建目录。
Project/
src/
*.h
*.cpp
cython/
Project.pyx
setup.py
答案 0 :(得分:5)
基本上我有3个文件夹:
CPROJECT
,C ++库:生成libcproject.so
共享对象CYPROJECT
,cythonized Python扩展:使用Cython生成cyproject.so
DEPENDENCIES
,依赖项:我复制两个项目的外部需求 在1中。我构建了C ++扩展(使用gcc - -shared
,-fPIC
编译选项编译),它将暴露给python并且{{1}依赖于向Python公开功能。作为后期处理命令,生成的CYPROJECT
将复制到.so
(以及DEPENDENCIES/libcproject/
个文件中)。这样,库当然也可以在纯C ++项目中独立使用。
2。我使用了3个子文件夹:
include
:主要包含C ++附加类(通常是从adapters
提供的类派生的类)。这些通常是通过特定于Cython需求的功能增强的类(例如存储目标Python版本的libcproject.so
C版本 - 继承自PyObject *
- 给定类和引用计数管理,通过object
和Py_XINCREF
,...)。Py_DECREF
:存储所有Cython手写的pyext
文件。.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=[]
)
]
)
将cython部分的所有手写.pyx
链接在一起[.pyx
]:
cyproject.pyx
注意:Cython生成的所有文件都保留在此include "pyext/Utils.pyx"
include "pyext/TCLAP.pyx"
include "pyext/LabSimulatorBase.pyx"
include "pyext/LabBinding.pyx"
include "pyext/LabSimulatorTime.pyx"
...
文件夹中,与预期的手写内容(setup
和adapters
完全分开)。
3。使用分隔的pyext
文件夹可以保持良好的分隔(如果我将移动DEPENDENCIES
- 及其依赖项 - 在其他环境中)
所有这些都是为了给你一个如何组织这类项目的概述(我希望是一个相关的概述)。