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