基本上我有3個文件夾:
CPROJECT
,C++庫:產生libcproject.so
共享對象
CYPROJECT
,該cythonized Python擴展:製造使用用Cython
DEPENDENCIES
的cyproject.so
,依賴關係:我複製兩個項目的外部需求
在1.我構建C++擴展(用gcc編譯 - -shared
,-fPIC
編譯選項),其將暴露於Python和該CYPROJECT
依賴於暴露的功能到Python。作爲後處理命令,生成的.so
被複制到DEPENDENCIES/libcproject/
(以及include
文件)中。這樣,該庫當然也可以在純C++項目中獨立使用。
在2.我使用3子文件夾:
adapters
:主要含有C++附加的類(通常從由libcproject.so
提供的那些派生類)。這些通常是增強了特定於Cython要求的功能的類(例如,通過Py_XINCREF
和Py_DECREF
,...)存儲給定類和參考計數管理的目標Python版本的PyObject *
C版本(繼承自object
) 。
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=[]
)
]
)
最後,主.pyx
,鏈接所有手寫的.pyx
s的cython部分[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
- 和它的依賴 - 在其他一些環境)。
所有這些給你一個關於如何組織這樣的項目的概述(我希望有一個相關的)。
你的C++項目可以在沒有Python的情況下使用嗎?創建並行ctypes,基於cffi的綁定(以支持更多不同交易的目標)提供相同的Python界面是否有意義? – jfs
@ J.F.Sebastian該項目可以並且應該在沒有Python的情況下使用(現在)。我不明白你的第二個問題。 – clstaudt
然後在邏輯上你有兩個項目:libproject(C++庫)和pyproject(允許使用Python中的libproject的Python模塊)。爲了便於使用(更容易從源代碼安裝並共同開發),您可以在pyproject中包含libproject。關於第二個問題:基於ctypes的綁定可能更容易在多個Python版本上部署。基於cffi的綁定可以用於更好的Pypy支持。例如,'pyinotify'既有基於ctypes的本地擴展,也有用C寫的本地擴展,'pyzmq'既有cffi也有基於Cython的實現。你是否需要它取決於你的項目。 – jfs