4. CおよびC ++拡張機能の構築—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.9/extending/building
移動先:案内検索

4.4。 CおよびC ++拡張機能の構築

CPythonのAC拡張機能は共有ライブラリです(例: Linuxでは.soファイル、Windowsでは.pyd)、初期化関数をエクスポートします。

共有ライブラリをインポートするには、 PYTHONPATH で使用可能であり、モジュール名にちなんで適切な拡張子を付けて名前を付ける必要があります。 distutilsを使用すると、正しいファイル名が自動的に生成されます。

初期化関数には次の署名があります。

PyObject *PyInit_modulename(void)

完全に初期化されたモジュール、または PyModuleDef インスタンスのいずれかを返します。 詳細については、 Cモジュールの初期化を参照してください。

ASCIIのみの名前のモジュールの場合、関数にはPyInit_<modulename>という名前を付け、<modulename>をモジュールの名前に置き換える必要があります。 マルチフェーズ初期化を使用する場合、非ASCIIモジュール名が許可されます。 この場合、初期化関数名はPyInitU_<modulename>で、<modulename>はPythonの punycode エンコードを使用してエンコードされ、ハイフンはアンダースコアに置き換えられます。 Pythonの場合:

def initfunc_name(name):
    try:
        suffix = b'_' + name.encode('ascii')
    except UnicodeEncodeError:
        suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
    return b'PyInit' + suffix

複数の初期化関数を定義することにより、単一の共有ライブラリから複数のモジュールをエクスポートすることができます。 ただし、デフォルトではファイル名に対応する関数のみが検出されるため、それらをインポートするには、シンボリックリンクまたはカスタムインポーターを使用する必要があります。 詳細については、 PEP 489「1つのライブラリ内の複数のモジュール」セクションを参照してください。

4.1。 distutilsを使用したCおよびC ++拡張機能の構築

拡張モジュールは、Pythonに含まれているdistutilsを使用して構築できます。 distutilsはバイナリパッケージの作成もサポートしているため、ユーザーは拡張機能をインストールするために必ずしもコンパイラとdistutilsを必要としません。

distutilsパッケージには、ドライバースクリプトsetup.pyが含まれています。 これはプレーンなPythonファイルであり、最も単純なケースでは、次のようになります。

from distutils.core import setup, Extension

module1 = Extension('demo',
                    sources = ['demo.c'])

setup (name = 'PackageName',
       version = '1.0',
       description = 'This is a demo package',
       ext_modules = [module1])

このsetup.pyとファイルdemo.cを使用して、実行中

python setup.py build

demo.cをコンパイルし、buildディレクトリにdemoという名前の拡張モジュールを生成します。 システムによっては、モジュールファイルはサブディレクトリbuild/lib.systemになり、demo.sodemo.pydのような名前になる場合があります。

setup.pyでは、すべての実行はsetup関数を呼び出すことによって実行されます。 これは可変数のキーワード引数を取りますが、上記の例ではサブセットのみを使用しています。 具体的には、この例では、パッケージをビルドするためのメタ情報を指定し、パッケージの内容を指定します。 通常、パッケージには、Pythonソースモジュール、ドキュメント、サブパッケージなどの追加モジュールが含まれます。 distutilsの機能の詳細については、 Pythonモジュールの配布(レガシーバージョン)のdistutilsドキュメントを参照してください。 このセクションでは、拡張モジュールの構築についてのみ説明します。

setup()の引数を事前に計算して、ドライバースクリプトをより適切に構成するのが一般的です。 上記の例では、 setup()ext_modules引数は拡張モジュールのリストであり、各拡張モジュールはExtensionのインスタンスです。 この例では、インスタンスはdemoという名前の拡張子を定義します。これは、単一のソースファイルdemo.cをコンパイルすることによってビルドされます。

多くの場合、追加のプリプロセッサ定義とライブラリが必要になる可能性があるため、拡張機能の構築はより複雑です。 これは、以下の例で示されています。

from distutils.core import setup, Extension

module1 = Extension('demo',
                    define_macros = [('MAJOR_VERSION', '1'),
                                     ('MINOR_VERSION', '0')],
                    include_dirs = ['/usr/local/include'],
                    libraries = ['tcl83'],
                    library_dirs = ['/usr/local/lib'],
                    sources = ['demo.c'])

setup (name = 'PackageName',
       version = '1.0',
       description = 'This is a demo package',
       author = 'Martin v. Loewis',
       author_email = '[email protected]',
       url = 'https://docs.python.org/extending/building',
       long_description = '''
This is really just a demo package.
''',
       ext_modules = [module1])

この例では、 setup()が追加のメタ情報とともに呼び出されます。これは、配布パッケージをビルドする必要がある場合に推奨されます。 拡張機能自体については、プリプロセッサ定義、インクルードディレクトリ、ライブラリディレクトリ、およびライブラリを指定します。 コンパイラーに応じて、distutilsはこの情報をさまざまな方法でコンパイラーに渡します。 たとえば、Unixでは、これによりコンパイルコマンドが発生する可能性があります

gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o

gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so

これらの行はデモンストレーションのみを目的としています。 distutilsユーザーは、distutilsが呼び出しを正しく行うことを信頼する必要があります。


4.2。 拡張モジュールの配布

拡張機能が正常に構築されたら、それを使用する3つの方法があります。

エンドユーザーは通常、モジュールをインストールしたいと思うでしょう、彼らは実行することによってそうします

python setup.py install

モジュールメンテナはソースパッケージを作成する必要があります。 そうするために、彼らは走ります

python setup.py sdist

場合によっては、追加のファイルをソースディストリビューションに含める必要があります。 これはMANIFEST.inファイルを介して行われます。 詳しくは、配布するファイルの指定をご覧ください。

ソースディストリビューションが正常に構築されている場合、メンテナはバイナリディストリビューションを作成することもできます。 プラットフォームに応じて、次のいずれかのコマンドを使用してこれを行うことができます。

python setup.py bdist_wininst
python setup.py bdist_rpm
python setup.py bdist_dumb