10

C++ プロジェクトに Python インターフェイスを提供したいと考えています。技術的には、C++ コードのラップに Cython を使用することにしました。時間が経つにつれて、プロジェクト全体が Python 拡張モジュールになる予定ですが、最初は非常に実験的なものです。徐々に、C++ クラスを Python に公開する必要があります。

私の質問は、Cython で生成された C++ コードと人間が作成した C++ コードが混在せず、Python 拡張モジュールが他のターゲットとは別にクリーンにビルドされるように、ファイルとビルド構成を最適に整理する方法です。

ソースファイル用のこのようなディレクトリ構造と、Cython 用のビルドディレクトリを想像します。

Project/
    src/
        *.h
        *.cpp
    cython/
        Project.pyx
        setup.py
4

1 に答える 1

5

基本的に私は3つのフォルダを持っています:

  1. CPROJECT、 C++ ライブラリ :libcproject.so共有オブジェクトの生成
  2. CYPROJECT、 cython 化された Python 拡張機能 : cyproject.soCython を使用して生成する
  3. DEPENDENCIES、依存関係:両方のプロジェクトの外部要件をコピーする場所

1では、 Python に公開され、機能を Python に公開するために依存するC++ 拡張 ( gcc - -shared-fPICコンパイル オプションでコンパイル)をビルドします。CYPROJECT後処理コマンドとして、結果が(ファイルと同様に).soにコピーされます。このようにして、ライブラリはもちろん、純粋な C++ プロジェクトでも独立して使用できます。DEPENDENCIES/libcproject/include

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

そして、ここに例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 部分の手書きの s を.pyxすべて[ ] にリンクする main :.pyxcyproject.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他の環境で-およびその依存関係を移動する場合に備えて)。

これらはすべて、この種のプロジェクトをどのように編成できるかについての概要 (適切なものであることを願っています) を提供するためのものです。

于 2013-05-29T05:39:01.250 に答える