Я хочу предоставить свой проект C ++ с интерфейсом Python. Технически я решил использовать Cython для переноса кода C ++. Со временем весь проект должен стать модулем расширения Python, но сначала это очень экспериментально. Постепенно классы C ++ должны быть доступны Python.
Мой вопрос заключается в том, как наилучшим образом организовать файлы и создать конфигурации так, чтобы сгенерированный Cython и написанный человеком код C ++ не смешивались, а модуль расширения Python был аккуратно собран отдельно от других целей.
Я представляю такую структуру каталогов для исходных файлов и некоторую директорию сборки для Cython.
Project/
src/
*.h
*.cpp
cython/
Project.pyx
setup.py
В основном у меня есть 3 папки:
CPROJECT
Библиотека C ++: создание libcproject.so
общий объектCYPROJECT
, Python расширение Python: создание cyproject.so
используя CythonDEPENDENCIES
, Зависимости: куда я копирую внешние требования для обоих проектовВ 1. Я строю расширение C ++ (скомпилировано с gcc — -shared
, -fPIC
параметры компиляции), которые будут выставлены на Python и что CYPROJECT
полагается на предоставление возможностей Python. В качестве команды постобработки .so
копируется в DEPENDENCIES/libcproject/
(так же хорошо как include
файлы). Таким образом, библиотека, конечно, может использоваться независимо в чистом C ++ проекте.
В 2. Я использую 3 подпапки:
adapters
: который в основном содержит дополнительные классы C ++ (часто это классы, производные от libcproject.so
). Обычно это классы, которые расширены функциональностью, специфичной для требований Cython (например, хранение PyObject *
Версия C целевой версии Python — унаследована от 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
(в основном, чтобы продемонстрировать, как дополнительный 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
с части 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
— и его зависимости — в какой-то другой среде).
Все это, чтобы дать вам обзор (я надеюсь, что он уместен) о том, как можно организовать проект такого рода.
Других решений пока нет …