Python 用 C++ 拡張機能の作成Create a C++ extension for Python

Python インタープリターの機能を拡張するため、およびオペレーティング システムの低レベル機能にアクセスするためには、C++ (または C) で記述されたモジュールがよく使われます。Modules written in C++ (or C) are commonly used to extend the capabilities of a Python interpreter as well as to enable access to low-level operating system capabilities. モジュールの主要な種類は次の 3 つです。There are three primary types of modules:

  • アクセラレータ モジュール: Python はインタープリター言語であるため、コードの特定の部分を C++ で書くことによってパフォーマンスを向上させることができます。Accelerator modules: because Python is an interpreted language, certain pieces of code can be written in C++ for higher performance.
  • ラッパー モジュール: 既存の C/C++ インターフェイスを Python コードに公開します。または、Python から使いやすい、より "Python らしい" API を公開します。Wrapper modules: expose existing C/C++ interfaces to Python code or expose a more "Pythonic" API that's easy to use from Python.
  • 低レベル システム アクセス モジュール: CPython ランタイム、オペレーティング システム、または基盤ハードウェアの低レベル機能にアクセスするために作成します。Low-level system access modules: created to access lower-level features of the CPython runtime, the operating system, or the underlying hardware.

この記事では、双曲正接を計算する CPython 用の C++ 拡張モジュールを作成し、Python コードからそれを呼び出す手順について説明します。This article walks through building a C++ extension module for CPython that computes a hyperbolic tangent and calls it from Python code. Python では最初にルーチンを実装して、C++ で同じルーチンを実装した場合の相対的なパフォーマンス向上を示します。The routine is implemented first in Python to demonstrate the relative performance gain of implementing the same routine in C++.

この記事では、Python で C++ を使用できるようにする 2 つの方法も示します。This article also demonstrates two ways to make the C++ available to Python:

これらの方法と他の方法の比較については、この記事の最後にある「別の方法」をご覧ください。A comparison between these and other means is found under alternative approaches at the end of this article.

このチュートリアルで使われているサンプルの完全版は python-samples-vs-cpp-extension (GitHub) にあります。The completed sample from this walkthrough can be found on python-samples-vs-cpp-extension (GitHub).

必須コンポーネントPrerequisites

  • C++ によるデスクトップ開発Python 開発ワークロードの両方を備えた Visual Studio 2017 以降が既定のオプションでインストールされます。Visual Studio 2017 or later with both the Desktop Development with C++ and Python Development workloads installed with default options.

  • Python 開発ワークロードでは、[Python ネイティブ開発ツール] の横のボックスもオンにします。In the Python Development workload, also select the box on the right for Python native development tools. このオプションによって、この記事で説明するほとんどの構成が設定されます。This option sets up most of the configuration described in this article. (このオプションには、C++ のワークロードも自動的に含まれます)。(This option also includes the C++ workload automatically.)

    [Python ネイティブ開発ツール] オプションの選択

    Tip

    データ サイエンスと分析アプリケーション ワークロードをインストールすることでも、Python と Python ネイティブ開発ツール オプションが既定で含まれます。Installing the Data science and analytical applications workload also includes Python and the Python native development tools option by default.

他のバージョンの Visual Studio の使用など、詳細については Visual Studio 用の Python サポートのインストールに関する記事をご覧ください。For more information, see Install Python support for Visual Studio, including using other versions of Visual Studio. Python を別にインストールする場合は、インストーラーで [詳細オプション][Download debugging symbols (デバッグ シンボルのダウンロード)][Download debug binaries (デバッグ バイナリのダウンロード)] を必ず選んでください。If you install Python separately, be sure to select Download debugging symbols and Download debug binaries under Advanced Options in the installer. このオプションを選択すると、デバッグ ビルドを行う場合に、必要なデバッグ ライブラリを確実に使用できます。This option ensures that you have the necessary debug libraries available if you choose to do a debug build.

Python アプリケーションを作成するCreate the Python application

  1. Visual Studio で [ファイル] > [新規] > [プロジェクト] の順に選択して、新しい Python プロジェクトを作成します。Create a new Python project in Visual Studio by selecting File > New > Project. "Python" を検索し、Python アプリケーション テンプレートを選択し、適切な名前と場所を指定し、[OK] を選択します。Search for "Python", select the Python Application template, give it a suitable name and location, and select OK.

  2. C++ を使用するには、32 ビットの Python インタープリターを使用する必要があります (Python 3.6 以降を推奨)。Working with C++ requires that you use a 32-bit Python interpreter (Python 3.6 or above recommended). Visual Studio の [ソリューション エクスプローラー] ウィンドウに、プロジェクト ノードを展開し、[Python 環境] ノードを展開します。In the Solution Explorer window of Visual Studio, expand the project node, then expand the Python Environments node. (太字またはグローバル デフォルト ラベルで) 既定として 32 ビット環境が表示されない場合、プロジェクト用の Python 環境の選択に関する記事の指示に従ってください。If you don't see a 32-bit environment as the default (either in bold, or labeled with global default), then follow the instructions on Select a Python environment for a project. 32 ビット インタープリターをインストールしていない場合、「Python インタープリターのインストール」をご覧ください。If you don't have a 32-bit interpreter installed, see Install Python interpreters.

  3. プロジェクトの .py ファイルに、双曲正接の計算をベンチマークする次のコードを貼り付けます (簡単に比較できるよう、数値演算ライブラリを使わずに実装されています)。In the project's .py file, paste the following code that benchmarks the computation of a hyperbolic tangent (implemented without using the math library for easier comparison). 自由に手動でコードを入力し、Python の編集機能を体験してください。Feel free to enter the code manually to experience some of the Python editing features.

    from itertools import islice
    from random import random
    from time import perf_counter
    
    COUNT = 500000  # Change this value depending on the speed of your computer
    DATA = list(islice(iter(lambda: (random() - 0.5) * 3.0, None), COUNT))
    
    e = 2.7182818284590452353602874713527
    
    def sinh(x):
        return (1 - (e ** (-2 * x))) / (2 * (e ** -x))
    
    def cosh(x):
        return (1 + (e ** (-2 * x))) / (2 * (e ** -x))
    
    def tanh(x):
        tanh_x = sinh(x) / cosh(x)
        return tanh_x
    
    def test(fn, name):
        start = perf_counter()
        result = fn(DATA)
        duration = perf_counter() - start
        print('{} took {:.3f} seconds\n\n'.format(name, duration))
    
        for d in result:
            assert -1 <= d <= 1, " incorrect values"
    
    if __name__ == "__main__":
        print('Running benchmarks with COUNT = {}'.format(COUNT))
    
        test(lambda d: [tanh(x) for x in d], '[tanh(x) for x in d] (Python implementation)')
    
  4. [デバッグ] > [デバッグなしで開始] (Ctrl + F5 キー) を使ってプログラムを実行し、結果を確認します。Run the program using Debug > Start without Debugging (Ctrl+F5) to see the results. COUNT 変数を調整して、ベンチマークの実行にかかる時間を変更することができます。You can adjust the COUNT variable to change how long the benchmark takes to run. このチュートリアルの目的は、ベンチマークの所要時間を約 2 秒にするように、カウントを設定することです。For the purposes of this walkthrough, set the count so that the benchmark take around two seconds.

Tip

ベンチマークを実行する場合は、常に [デバッグ] > [デバッグなしで開始] を使用して、Visual Studio デバッガー内でコードを実行するときに発生するオーバーヘッドを回避します。When running benchmarks, always use Debug > Start without Debugging to avoid the overhead incurred when running code within the Visual Studio debugger.

C++ のコア プロジェクトを作成するCreate the core C++ projects

"superfastcode"と"superfastcode2"という 2 つの同じ C++ プロジェクトを作成するには、このセクションの手順に従います。Follow the instructions in this section to create two identical C++ projects named "superfastcode" and "superfastcode2". 後で、各プロジェクトで別の手段を使用して C++ コードを Python に公開します。Later you'll use different means in each project to expose the C++ code to Python.

  1. PYTHONHOME 環境変数が使用する Python インタープリターに設定されていることを確認してください。Make sure the PYTHONHOME environment variable is set to the Python interpreter you want to use. Visual Studio の C++ プロジェクトは、この変数に戻づいて、Python 拡張機能の作成時に使用される python.h などのファイルを見つけます。The C++ projects in Visual Studio rely on this variable to locate files such as python.h, which are used when creating a Python extension.

  2. ソリューション エクスプローラーで、ソリューションを右クリックし、[追加] > [新しいプロジェクト] の順に選択します。Right-click the solution in Solution Explorer and select Add > New Project. Visual Studio ソリューションには、Python プロジェクトと C++ プロジェクトの両方を含めることができます (これは Visual Studio for Python 使用の利点の 1 つです)。A Visual Studio solution can contain both Python and C++ projects together (which is one of the advantages of using Visual Studio for Python).

  3. "C++" を検索し、[空のプロジェクト] を選択し、"superfastcode" という名前 (2 番目のプロジェクトには "superfastcode2") を指定して [OK] を選択します。Search on "C++", select Empty project, specify the name "superfastcode" ("superfastcode2" for the second project), and select OK.

    Tip

    Visual Studio で Python ネイティブ開発ツールをインストールしたので、代わりに Python 拡張モジュールから始めることができます。このテンプレートには、以下で説明するものの多くが既に配置されています。With the Python native development tools installed in Visual Studio, you can start with the Python Extension Module template instead, which has much of what's described below already in place. ただし、このチュートリアルでは、拡張モジュールの作成手順を実際に示すため、空のプロジェクトから始めます。For this walkthrough, though, starting with an empty project demonstrates building the extension module step by step. プロセスを理解したら、独自の拡張を記述するとき、テンプレートで時間が節約されます。Once you understand the process, the template saves you time when writing your own extensions.

  4. [ソース ファイル] ノードを右クリックして [追加] > [新しい項目] の順に選択し、[C++ ファイル] を選択して module.cpp という名前を付け、[OK] を選択し、新しいプロジェクトに C++ ファイルを作成します。Create a C++ file in the new project by right-clicking the Source Files node, then select Add > New Item, select C++ File, name it module.cpp, and select OK.

    Important

    後続の手順で C++ プロパティ ページを有効にするには、.cpp 拡張子を持つファイルが必要です。A file with the .cpp extension is necessary to turn on the C++ property pages in the steps that follow.

  5. ソリューション エクスプローラーで C++ プロジェクトを右クリックして、[プロパティ] を選択します。Right-click the C++ project in Solution Explorer, select Properties.

  6. 表示される [プロパティ ページ] ダイアログ ボックスの上部で、[構成][すべての構成] に、[プラットフォーム][Win32] に設定します。At the top of the Property Pages dialog that appears, set Configuration to All Configurations and Platform to Win32.

  7. 次の表に示すように、特定のプロパティを設定し、[OK] を選択します。Set the specific properties as described in the following table, then select OK.

    タブTab プロパティProperty [値]Value
    全般General [全般] > [ターゲット名]General > Target Name from...import ステートメントで Python からモジュールを参照するときのモジュール名を指定します。Specify the name of the module as you want to refer to it from Python in from...import statements. この名前は、Python のモジュールを定義するときに C++ でも使用します。You use this same name in the C++ when defining the module for Python. プロジェクトの名前をモジュール名として使用する場合は、既定値の $(ProjectName) のままにしておきます。If you want to use the name of the project as the module name, leave the default value of $(ProjectName).
    [全般] > [ターゲットの拡張子]General > Target Extension .pyd.pyd
    [プロジェクトの既定値] > [構成の種類]Project Defaults > Configuration Type ダイナミック ライブラリ (.dll)Dynamic Library (.dll)
    [C/C++] > [全般]C/C++ > General 追加のインクルード ディレクトリAdditional Include Directories インストールに合わせて Python の include フォルダーを追加します (例: c:\Python36\include)。Add the Python include folder as appropriate for your installation, for example, c:\Python36\include.
    [C/C++] > [プリプロセッサ]C/C++ > Preprocessor プリプロセッサの定義Preprocessor Definitions CPython のみ: 文字列の先頭に Py_LIMITED_API; (セミコロンを含む) を追加します。CPython only: add Py_LIMITED_API; to the beginning of the string (including the semicolon). この定義により、Python から呼び出すことができる一部の関数を制限し、Python の異なるバージョン間でのコードの移植性を高くします。This definition restricts some of the functions you can call from Python and makes the code more portable between different versions of Python. PyBind11 を使用している場合は、この定義を追加しないでください。追加すると、ビルド エラーが発生します。If you're working with PyBind11, don't add this definition, otherwise you'll see build errors.
    [C/C++] > [コード生成]C/C++ > Code Generation ランタイム ライブラリRuntime Library マルチスレッド DLL (/MD) (下記の「警告」を参照)Multi-threaded DLL (/MD) (see Warning below)
    [リンカー] > [全般]Linker > General 追加のライブラリ ディレクトリAdditional Library Directories インストールに合わせて、.lib ファイルが含まれる Python の libs フォルダーを追加します (例: c:\Python36\libs)。Add the Python libs folder containing .lib files as appropriate for your installation, for example, c:\Python36\libs. (.py ファイルが含まれる Lib フォルダーではなく.lib ファイルが含まれる libs フォルダーを必ず指定してください)。(Be sure to point to the libs folder that contains .lib files, and not the Lib folder that contains .py files.)

    Tip

    プロジェクトのプロパティに [C/C++] タブが表示されない場合は、C/C++ ソース ファイルとして識別されるファイルがプロジェクトに含まれないためです。If you don't see the C/C++ tab in the project properties, it's because the project doesn't contain any files that it identifies as C/C++ source files. このような条件は、.c または .cpp 拡張子を付けずにソース ファイルを作成すると発生する可能性があります。This condition can occur if you create a source file without a .c or .cpp extension. たとえば、前の [新しい項目] ダイアログで、つい module.cpp ではなく module.coo と入力してしまった場合、Visual Studio はファイルを作成しますが、ファイルの種類を "C/C++ コード" に設定しないので、C/C++ のプロパティ タブがアクティブになりません。このような識別の誤処理は、ファイル名を .cpp に変更しても解決しません。For example, if you accidentally entered module.coo instead of module.cpp in the new item dialog earlier, then Visual Studio creates the file but doesn't set the file type to "C/C+ Code," which is what activates the C/C++ properties tab. Such misidentification remains the case even if you rename the file with .cpp. ファイルの種類を正しく設定するには、ソリューション エクスプローラーでファイルを右クリックして [プロパティ] を選び、[ファイルの種類][C/C++ コード] に設定します。To set the file type properly, right-click the file in Solution Explorer, select Properties, then set File Type to C/C++ Code.

    Warning

    デバッグ構成の場合でも [C/C++] > [コード生成] > [ランタイム ライブラリ] のオプションを常に マルチスレッド DLL (/MD) に設定します。これは、この設定がデバッグ以外の Python バイナリのビルドに使用されるためです。Always set the C/C++ > Code Generation > Runtime Library option to Multi-threaded DLL (/MD), even for a debug configuration, because this setting is what the non-debug Python binaries are built with. CPython でマルチスレッド デバッグ DLL (/MDd) オプションを設定する場合、デバッグ構成をビルドすると、エラー "C1189:Py_LIMITED_API は、Py_DEBUG、Py_TRACE_REFS、Py_REF_DEBUG に対応していません" が生成されます。With CPython, if you happen to set the Multi-threaded Debug DLL (/MDd) option, building a Debug configuration produces error C1189: Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, and Py_REF_DEBUG. さらに、ビルド エラーを避けるために Py_LIMITED_API を削除すると (CPython では必要ですが、PyBind11 では不要)、モジュールをインポートしようとしたときに Python がクラッシュしますFurthermore, if you remove Py_LIMITED_API (which is required with CPython, but not PyBind11) to avoid the build error, Python crashes when attempting to import the module. (後で説明しますが、クラッシュは DLL の PyModule_Create の呼び出し内で発生し、出力メッセージは "Fatal Python error: PyThreadState_Get: no current thread" (Python 致命的なエラー: PyThreadState_Get: 現在のスレッドがありません) です)。(The crash happens within the DLL's call to PyModule_Create as described later, with the output message of Fatal Python error: PyThreadState_Get: no current thread.)

    /MDd オプションは Python デバッグ バイナリ (python_d.exe など) のビルドに使われますが、拡張 DLL に対して選ぶと、やはり Py_LIMITED_API のビルド エラーになります。The /MDd option is used to build the Python debug binaries (such as python_d.exe), but selecting it for an extension DLL still causes the build error with Py_LIMITED_API.

  8. C++ プロジェクトを右クリックし、[ビルド] を選んで構成をテストします (デバッグリリースの両方)。Right-click the C++ project and select Build to test your configurations (both Debug and Release). .pyd ファイルは、C++ のプロジェクト フォルダー自体ではなく、Debug および Release の下の solution フォルダーにあります。The .pyd files are located in the solution folder under Debug and Release, not the C++ project folder itself.

  9. C++ プロジェクトの module.cpp ファイルに、次のコードを追加します。Add the following code to the C++ project's module.cpp file:

    #include <Windows.h>
    #include <cmath>
    
    const double e = 2.7182818284590452353602874713527;
    
    double sinh_impl(double x) {
        return (1 - pow(e, (-2 * x))) / (2 * pow(e, -x));
    }
    
    double cosh_impl(double x) {
        return (1 + pow(e, (-2 * x))) / (2 * pow(e, -x));
    }
    
    double tanh_impl(double x) {
        return sinh_impl(x) / cosh_impl(x);
    }
    
  10. C++ プロジェクトを再度ビルドし、コードが正しいことを確認します。Build the C++ project again to confirm that your code is correct.

  11. まだ行っていない場合は、上記の手順を繰り返して、同じコンテンツを持つ "superfastcode2" という名前の 2 番目のプロジェクトを作成します。If you haven't already done so, repeat the steps above to create a second project named "superfastcode2" with identical contents.

C++ プロジェクトを Python の拡張機能に変換するConvert the C++ projects to extensions for Python

C++ DLL を Python の拡張機能にするには、まず Python の型と対話するようにエクスポートしたメソッドを変更します。To make the C++ DLL into an extension for Python, you first modify the exported methods to interact with Python types. その後、モジュールのメソッドの定義と共に、モジュールをエクスポートする関数を追加します。You then add a function that exports the module, along with definitions of the module's methods.

次のセクションでは、CPython の拡張機能と PyBind11 の両方を使用してこれらの手順を実行する方法について説明します。The sections that follow explain how to perform these steps using both the CPython extensions and PyBind11.

CPython の拡張機能CPython extensions

このセクションに登場する Python 3.x の機能の背景については、python.org の「Python/C API リファレンスマニュアル」を参照してください。特に、「モジュールオブジェクト」を参照してください。右上にあるドロップダウン コントロールから必ずお使いのバージョンの Python を選択すると該当文書が表示されます。For background on what's shown in this section for Python 3.x, refer to the Python/C API Reference Manual and especially Module Objects on python.org (remember to select your version of Python from the drop-down control on the upper right to view the correct documentation).

Python 2.7 を使用している場合は、代わりに python.org で C や C++ による Python 2.7 の拡張に関するページや「Python 3 への拡張モジュール移植」を参照してください。If you're working with Python 2.7, refer instead to Extending Python 2.7 with C or C++ and Porting Extension Modules to Python 3 (python.org).

  1. module.cppの上部で、Python.h を含めます。At the top of module.cpp, include Python.h:

    #include <Python.h>
    
  2. Python の型 (つまり PyOjbect*) を受け付けて戻すように、tanh_impl メソッドを変更します。Modify the tanh_impl method to accept and return Python types (a PyOjbect*, that is):

    PyObject* tanh_impl(PyObject *, PyObject* o) {
        double x = PyFloat_AsDouble(o);
        double tanh_x = sinh_impl(x) / cosh_impl(x);
        return PyFloat_FromDouble(tanh_x);
    }
    
  3. Python に対して C++ の tanh_impl 関数を提示する方法を定義する構造体を追加します。Add a structure that defines how the C++ tanh_impl function is presented to Python:

    static PyMethodDef superfastcode_methods[] = {
        // The first property is the name exposed to Python, fast_tanh, the second is the C++
        // function name that contains the implementation.
        { "fast_tanh", (PyCFunction)tanh_impl, METH_O, nullptr },
    
        // Terminate the array with an object containing nulls.
        { nullptr, nullptr, 0, nullptr }
    };
    
  4. Python コードで参照するモジュールを定義する構造体を追加します。特に、from...import ステートメントを利用するタイミングを定義します。Add a structure that defines the module as you want to refer to it in your Python code, specifically when using the from...import statement. (これが、[構成プロパティ] > [全般] > [ターゲット名] の、プロジェクトのプロパティの値と一致するようにします)。次の例では、"superfastcode" というモジュール名は Python で from superfastcode import fast_tanh を使用できることを意味します。fast_tanhsuperfastcode_methods 内で定義されているためです。(Make this match the value in the project properties under Configuration Properties > General > Target Name.) In the following example, the "superfastcode" module name means you can use from superfastcode import fast_tanh in Python, because fast_tanh is defined within superfastcode_methods. (module.cpp などの、C++ プロジェクト内部のファイル名は重要ではありません)。(Filenames internal to the C++ project, like module.cpp, are inconsequential.)

    static PyModuleDef superfastcode_module = {
        PyModuleDef_HEAD_INIT,
        "superfastcode",                        // Module name to use with Python import statements
        "Provides some functions, but faster",  // Module description
        0,
        superfastcode_methods                   // Structure that defines the methods of the module
    };
    
  5. モジュールを読み込むときに Python が呼び出すメソッドを追加します。PyInit_<module-name> という名前にする必要があります。<module_name> は、C++ プロジェクトの [全般] > [ターゲット名] プロパティと正確に一致します (つまり、プロジェクトによってビルドされる .pyd のファイル名と一致します)。Add a method that Python calls when it loads the module, which must be named PyInit_<module-name>, where <module-name> exactly matches the C++ project's General > Target Name property (that is, it matches the filename of the .pyd built by the project).

    PyMODINIT_FUNC PyInit_superfastcode() {
        return PyModule_Create(&superfastcode_module);
    }
    
  6. ターゲットの構成をリリースに設定し、もう一度 C++ プロジェクトをビルドして、コードを検証します。Set the target configuration to Release and build the C++ project again to verify your code. エラーが発生した場合は、以下の「トラブルシューティング」セクションをご覧ください。If you encounter errors, see the Troubleshooting section below.

PyBind11PyBind11

前のセクションの手順を完了すると、C++ コードに必要なモジュール構造を作成するために多数の定型コードを使用したことに気付きます。If you completed the steps in the previous section, you certainly noticed that you used lots of boilerplate code to create the necessary module structures for the C++ code. PyBind11 は、はるかに少ないコードで同じ結果を実現する C++ ヘッダー ファイルのマクロを使用してプロセスを簡略化します。PyBind11 simplifies the process through macros in a C++ header file that accomplish the same result with much less code. このセクションに表示される内容の背景については、PyBind11 の基本 (github.com) を参照してください。For background on what's shown in this section, see PyBind11 basics (github.com).

  1. pip (pip install pybind11 または py -m pip install pybind11) を使用して PyBind11 をインストールします。Install PyBind11 using pip: pip install pybind11 or py -m pip install pybind11.

  2. module.cppの上部で、pybind11.h を含めます。At the top of module.cpp, include pybind11.h:

    #include <pybind11/pybind11.h>
    
  3. module.cpp の下部で、PYBIND11_MODULE マクロを使用して C++ 関数にエントリ ポイントを定義します。At the bottom of module.cpp, use the PYBIND11_MODULE macro to define the entrypoint to the C++ function:

    namespace py = pybind11;
    
    PYBIND11_MODULE(superfastcode2, m) {
        m.def("fast_tanh2", &tanh_impl, R"pbdoc(
            Compute a hyperbolic tangent of a single argument expressed in radians.
        )pbdoc");
    
    #ifdef VERSION_INFO
        m.attr("__version__") = VERSION_INFO;
    #else
        m.attr("__version__") = "dev";
    #endif
    }
    
  4. ターゲットの構成をリリースに設定し、C++ プロジェクトをビルドして、コードを検証します。Set the target configuration to Release and build the C++ project to verify your code. エラーが発生した場合は、次のトラブルシューティングをご覧ください。If you encounter errors, see the next section on troubleshooting.

トラブルシューティングTroubleshooting

C++ モジュールは、次の理由でコンパイルに失敗する場合があります。The C++ module may fail to compile for the following reasons:

  • Python.h が見つかりません (E1696: ソース ファイル "Python.h" を開くことができませんでした かつ/または C1083: インクルード ファイル "Python.h" を開くことができません: ファイルまたはディレクトリが存在しません): プロジェクトのプロパティの [C/C++] > [全般] > [追加のインクルード ディレクトリ] のパスが、Python インストールの include フォルダーをポイントしていることを確認します。Unable to locate Python.h (E1696: cannot open source file "Python.h" and/or C1083: Cannot open include file: "Python.h": No such file or directory): verify that the path in C/C++ > General > Additional Include Directories in the project properties points to your Python installation's include folder. C++ のコア プロジェクトを作成する」の手順 6 をご覧ください。See step 6 under Create the core C++ project.

  • Python ライブラリが見つかりません: プロジェクトのプロパティの [リンカー] > [全般] > [追加のライブラリ ディレクトリ] のパスが、Python インストールの libs フォルダーを指していることを確認します。Unable to locate Python libraries: verify that the path in Linker > General > Additional Library Directories in the project properties points to your Python installation's libs folder. C++ のコア プロジェクトを作成する」の手順 6 をご覧ください。See step 6 under Create the core C++ project.

  • ターゲット アーキテクチャに関連するリンカー エラー: C++ プロジェクトのターゲット アーキテクチャを、Python インストールのアーキテクチャと一致するように変更します。Linker errors related to target architecture: change the C++ target's project architecture to match that of your Python installation. たとえば、C++ プロジェクトで x64 をターゲットとするが、Python インストールが x86 の場合は、C++ プロジェクトを x86 をターゲットとするように変更します。For example, if you're targeting x64 with the C++ project but your Python installation is x86, change the C++ project to target x86.

コードをテストして結果を比較するTest the code and compare the results

これで、Python 拡張機能の構造の DLL ができたので、Python プロジェクトからそれらを参照し、モジュールをインポートして、それらのメソッドを使うことができます。Now that you have the DLLs structured as Python extensions, you can refer to them from the Python project, import the modules, and use their methods.

Python で DLL を使用できるようするMake the DLL available to Python

Python で DLL を使えるようにするには 2 つの方法があります。There are two ways to make the DLL available to Python.

Python プロジェクトと C++ プロジェクトが同じソリューション内にある場合は、1 つ目の方法を使用します。The first method works if the Python project and the C++ project are in the same solution. ソリューション エクスプローラーに移動し、Python プロジェクト内の [参照設定] ノードを右クリックし、[参照の追加] をクリックします。Go to Solution Explorer, right-click the References node in your Python project, and then select Add Reference. 表示されるダイアログで [プロジェクト] タブを選択し、superfastcode プロジェクトと superfastcode2 プロジェクトの両方を選択し、[OK] を選択します。In the dialog that appears, select the Projects tab, select both the superfastcode and superfastcode2 projects, and then select OK.

superfastcode プロジェクトに参照を追加する

次の手順で説明する別の方法では、グローバル Python 環境にモジュールをインストールし、他の Python プロジェクトでも使えるようにします The alternate method, described in the following steps, installs the module in the global Python environment, making it available to other Python projects as well. (そのためには、通常、その環境に合わせて Visual Studio 2017 バージョン 15.5 以前で IntelliSense 入力候補データベースを更新する必要があります。(Doing so typically requires that you refresh the IntelliSense completion database for that environment in Visual Studio 2017 version 15.5 and earlier. 環境からモジュールを削除するときも、更新する必要があります)。Refreshing is also necessary when removing the module from the environment.)

  1. Visual Studio 2017 以降を使っている場合は、Visual Studio インストーラーを実行して [変更] を選び、[個別のコンポーネント] > [コンパイラ、ビルド ツール、およびランタイム] > [Visual C++ 2015.3 v140 ツールセット] を選びます。If you're using Visual Studio 2017 or later, run the Visual Studio installer, select Modify, select Individual Components > Compilers, build tools, and runtimes > Visual C++ 2015.3 v140 toolset. この手順が必要な理由は、Python (for Windows) 自体が Visual Studio 2015 (バージョン 14.0) でビルドされ、ここで説明する方法で拡張機能をビルドするときはこれらのツールが使えることが想定されるためです。This step is necessary because Python (for Windows) is itself built with Visual Studio 2015 (version 14.0) and expects that those tools are available when building an extension through the method described here. (32 ビット バージョンの Python をインストールし、DLL を x64 ではなく Win32 にターゲットする必要がある場合があることに注意してください)。(Note that you may need to install a 32-bit version of Python and target the DLL to Win32 and not x64.)

  2. プロジェクトを右クリックし、[追加] > [新しい項目] を選択して、C++ プロジェクトに setup.py という名前のファイルを作成します。Create a file named setup.py in the C++ project by right-clicking the project and selecting Add > New Item. 次に、C++ File (.cpp) を選択し、ファイルに setup.py という名前を付け、[OK] を選択します (.py 拡張子を使用してファイルに名前を付けることで、C++ ファイル テンプレートを使用していても、Visual Studio でそのファイルが Python として認識されるようにします)。Then select C++ File (.cpp), name the file setup.py, and select OK (naming the file with the .py extension makes Visual Studio recognize it as Python despite using the C++ file template). ファイルがエディターに表示されたら、拡張メソッドに応じて、そこに次のコードを貼り付けます。When the file appears in the editor, paste the following code into it as appropriate to the extension method:

    CPython の拡張機能 (superfastcode プロジェクト):CPython extensions (superfastcode project):

    from distutils.core import setup, Extension, DEBUG
    
    sfc_module = Extension('superfastcode', sources = ['module.cpp'])
    
    setup(name = 'superfastcode', version = '1.0',
        description = 'Python Package with superfastcode C++ extension',
        ext_modules = [sfc_module]
        )
    

    このスクリプトについては、「Building C and C++ Extensions」 (C と C++ の拡張機能のビルド) (python.org) をご覧ください。See Building C and C++ extensions (python.org) for documentation on this script.

    PyBind11 (superfastcode2 プロジェクト):PyBind11 (superfastcode2 project):

    import os, sys
    
    from distutils.core import setup, Extension
    from distutils import sysconfig
    
    cpp_args = ['-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.7']
    
    sfc_module = Extension(
        'superfastcode2', sources = ['module.cpp'],
        include_dirs=['pybind11/include'],
        language='c++',
        extra_compile_args = cpp_args,
        )
    
    setup(
        name = 'superfastcode2',
        version = '1.0',
        description = 'Python package with superfastcode2 C++ extension (PyBind11)',
        ext_modules = [sfc_module],
    )
    
  3. setup.py コードをコマンド ラインから使用すると、Visual Studio 2015 C++ ツールセット使って拡張機能をビルドするように Python に指示します。The setup.py code instructs Python to build the extension using the Visual Studio 2015 C++ toolset when used from the command line. 管理者特権でコマンド プロンプトを開き、C++ プロジェクトを含むフォルダー (つまり setup.py を含むフォルダー) に移動して、次のコマンドを入力します。Open an elevated command prompt, navigate to the folder containing the C++ project (that is, the folder that contains setup.py), and enter the following command:

    pip install .
    

    またはor:

    py -m pip install .
    

Python から DLL を呼び出すCall the DLL from Python

前のセクションで説明したように、Python で DLL を使用できるようにすると、Python コードから superfastcode.fast_tanh 関数と superfastcode2.fast_tanh2 関数を呼び出して、それらのパフォーマンスを Python の実装と比較できるようになります。After you've made the DLL available to Python as described in the previous section, you can now call the superfastcode.fast_tanh and superfastcode2.fast_tanh2 functions from Python code and compare their performance to the Python implementation:

  1. 次の行を .py ファイルに追加して、DLL からエクスポートされたメソッドを呼び出してその出力を表示します。Add the following lines in your .py file to call methods exported from the DLLs and display their outputs:

    from superfastcode import fast_tanh
    test(lambda d: [fast_tanh(x) for x in d], '[fast_tanh(x) for x in d] (CPython C++ extension)')
    
    from superfastcode2 import fast_tanh2
    test(lambda d: [fast_tanh2(x) for x in d], '[fast_tanh2(x) for x in d] (PyBind11 C++ extension)')
    
  2. Python プログラムを実行 ([デバッグ] > [デバッグなしで開始] または Ctrl+F5 キー) し、Python の実装よりも約 5 から 20 倍高速で C++ のルーチンが実行されることを確認します。Run the Python program (Debug > Start without Debugging or Ctrl+F5) and observe that the C++ routines run approximately five to twenty times faster than the Python implementation. 通常、次のような出力が表示されます。Typical output appears as follows:

    Running benchmarks with COUNT = 500000
    [tanh(x) for x in d] (Python implementation) took 0.758 seconds
    
    [fast_tanh(x) for x in d] (CPython C++ extension) took 0.076 seconds
    
    [fast_tanh2(x) for x in d] (PyBind11 C++ extension) took 0.204 seconds
    

    [デバッグなしで開始] コマンドが無効な場合、ソリューション エクスプローラーで Python プロジェクトを右クリックして、[スタートアップ プロジェクトに設定] を選択します。If the Start Without Debugging command is disabled, right-click the Python project in Solution Explorer and select Set as Startup Project.

  3. 違いがより顕著になるように COUNT 変数を増やしてみてください。Try increasing the COUNT variable so that the differences are more pronounced. また、C++ モジュールのデバッグ ビルドの実行は、リリース ビルドよりも低速になります。これは、デバッグ ビルドが十分に最適化されず、さまざまなエラー チェックが含まれるためです。A Debug build of the C++ module also runs slower than a Release build because the Debug build is less optimized and contains various error checks. これらの構成間を自由に切り替えて比較することができます。Feel free to switch between those configurations for comparison.

Note

出力で、PyBind11 拡張機能が CPython 拡張機能ほど高速ではないものの、Python をそのまま実装した場合よりも大幅に高速であることが確認できます。In the output, you can see that the PyBind11 extension isn't as fast as the CPython extension, though it's still significantly faster than the straight Python implementation. この差は、C++ インターフェイスを劇的に簡素化するために、PyBind11 によってもたらされる呼び出しごとの少量のオーバーヘッドによるものです。The difference is due to a small amount of per-call overhead that PyBind11 introduces in order to make its C++ interface dramatically simpler. この呼び出しごとの差は、実際には完全に無視できるほど小さいものです。テスト コードは、extension 関数を 500,000 回呼び出すため、ここに表されている結果には、そのオーバーヘッドが大幅に増幅されています。This per-call difference is actually quite negligible: because the test code calls the extension functions 500,000 times, the results you see here greatly amplify that overhead! 通常、C++ 関数は、ここで使用されている単純な fast_tanh[2] メソッドよりもずっと多くの作業を行っており、この場合にはオーバーヘッドは重要ではありません。Typically, a C++ function does much more work than the trivial fast_tanh[2] methods used here, in which case the overhead is unimportant. ただし、1 秒あたり何千回も呼び出される可能性があるメソッドを実装する場合は、CPython のアプローチを使用することで、PyBind11 よりも高いパフォーマンスを実現できます。However, if you're implementing methods that might be called thousands of times per second, using the CPython approach can result in better performance than PyBind11.

C++ コードをデバッグするDebug the C++ code

Visual Studio では、Python と C++ コードを一緒にデバッグすることをサポートしています。Visual Studio supports debugging Python and C++ code together. このセクションでは、superfastcode プロジェクトを使用するプロセスについて説明します。この手順は、superfastcode2 プロジェクトでも同じです。This section walks through the process using the superfastcode project; the steps are the same for the superfastcode2 project.

  1. ソリューション エクスプローラーで Python プロジェクトを右クリックして、[プロパティ][デバッグ] タブを選び、[デバッグ] > [ネイティブ コードのデバッグを有効にする] オプションをオンにします。Right-click the Python project in Solution Explorer, select Properties, select the Debug tab, and then select the Debug > Enable native code debugging option.

    Tip

    ネイティブ コードのデバッグを有効にすると、プログラムが通常の [続行するには、任意のキーを押してください] で一時停止せずに完了した場合に、Python の出力ウィンドウがすぐに消えることがあります。When you enable native code debugging, the Python output window may disappear immediately when the program has completed without giving you the usual Press any key to continue pause. 強制的に一時停止するには、ネイティブ コードのデバッグを有効にするときに、[デバッグ] タブの [実行] > [インタープリターの引数] フィールドに、-i オプションを追加します。To force a pause, add the -i option to the Run > Interpreter Arguments field on the Debug tab when you enable native code debugging. この引数を使用すると、Python インタープリターはコード終了後に対話モードになり、この時点でユーザーが Ctrl + Z > Enter キーを押して終了するのを待機します。This argument puts the Python interpreter into interactive mode after the code finishes, at which point it waits for you to press Ctrl+Z > Enter to exit. (または、Python コードを変更してもよい場合は、プログラムの最後に import os および os.system("pause") ステートメントを追加します。(Alternately, if you don't mind modifying your Python code, you can add import os and os.system("pause") statements at the end of your program. このコードで、元の一時停止プロンプトが複製されます)。This code duplicates the original pause prompt.)

  2. [ファイル] > [保存] を選択して、プロパティの変更を保存します。Select File > Save to save the property changes.

  3. Visual Studio ツールバーで、ビルド構成を [デバッグ] に設定します。Set the build configuration to Debug in the Visual Studio toolbar.

    ビルド構成を [デバッグ] に設定する

  4. 通常デバッガーでコードを実行するとより時間がかかるため、.py ファイルの COUNT 変数を約 5 倍小さい値 (たとえば、500000 から 100000) に変更できます。Because code generally takes longer to run in the debugger, you may want to change the COUNT variable in your .py file to a value that's about five times smaller (for example, change it from 500000 to 100000).

  5. C++ コードで tanh_impl メソッドの先頭行にブレークポイントを設定して、(F5 キーを押すか、[デバッグ] > [デバッグの開始] の順に選択して) デバッガーを開始します。In your C++ code, set a breakpoint on the first line of the tanh_impl method, then start the debugger (F5 or Debug > Start Debugging). そのコードが呼び出されるとデバッガーが停止します。The debugger stops when that code is called. ブレークポイントがヒットしない場合は、構成が [デバッグ] に設定されていること、およびプロジェクトを保存していること (これはデバッガーの開始時に自動的に行われません) を確認します。If the breakpoint is not hit, check that the configuration is set to Debug and that you've saved the project (which does not happen automatically when starting the debugger).

    C++ コードのブレークポイントでの停止

  6. この時点で、C++ コードをステップ実行したり、変数を調べたりできます。At this point you can step through the C++ code, examine variables, and so on. これらの機能の詳細については、「Python と C++ を同時にデバッグする」をご覧ください。These features are detailed in Debug C++ and Python together.

別の方法Alternative approaches

次の表で説明するように、Python の拡張機能を作成するにはさまざまな方法があります。There are a variety of means to create Python extensions as described in the following table. CPython と PyBind11 の最初の 2 つのエントリは、この記事で既に説明しています。The first two entries for CPython and PyBind11 are what has been discussed in this article already.

方法Approach 時期Vintage 代表的ユーザーRepresentative user(s) 長所Pro(s) 短所Con(s)
CPython 用の C/C++ 拡張モジュールC/C++ extension modules for CPython 19911991 標準ライブラリStandard Library 広範なドキュメントとチュートリアルExtensive documentation and tutorials. 総合的な制御。Total control. コンパイル、移植性、参照の管理。Compilation, portability, reference management. C についての深い知識。High C knowledge.
PyBind11 (C++ 向けに推奨)PyBind11 (Recommended for C++) 20152015 既存の C++ コードの Python バインディングを作成するためのヘッダーのみの軽量ライブラリ。Lightweight, header-only library for creating Python bindings of existing C++ code. 依存関係はわずか。Few dependencies. PyPy 互換性。PyPy compatibility. 新しく、未完成な部分あり。Newer, less mature. C++ 11 の機能を多用。Heavy use of C++11 features. 対応しているコンパイラが少ない (Visual Studio は含まれる)。Short list of supported compilers (Visual Studio is included).
Cython (C に推奨)Cython (Recommended for C) 20072007 geventkivygevent, kivy Python に似ている。Python-like. 非常に完成されている。Highly mature. 高パフォーマンス。High performance. コンパイル、新しい構文、新しいツールチェーン。Compilation, new syntax, new toolchain.
Boost.PythonBoost.Python 20022002 ほぼすべての C++ コンパイラで動作。Works with just about every C++ compiler. ライブラリ スイートが大きくて複雑。使用していないコンパイラの回避策が多く含まれる。Large and complex suite of libraries; contains many workarounds for old compilers.
ctypesctypes 20032003 oscryptooscrypto コンパイルがなく、広く利用可能。No compilation, wide availability. C 構造体のアクセスや変更が煩雑で、エラーを起こしやすい。Accessing and mutating C structures cumbersome and error prone.
SWIGSWIG 19961996 crfsuitecrfsuite 多くの言語のバインドを一度に生成。Generate bindings for many languages at once. Python が唯一のターゲットである場合、過剰なオーバーヘッド。Excessive overhead if Python is the only target.
cfficffi 20132013 cryptographypypycryptography, pypy 容易な統合、PyPy との互換性。Ease of integration, PyPy compatibility. 新しく、未完成な部分あり。Newer, less mature.
cppyycppyy 20172017 C++ を使用する場合の cffi と似ている。Similar to cffi using C++. 新しく、VS 2017 では問題が発生する可能性がある。Newer, may have some issues with VS 2017.

関連項目See also

このチュートリアルで使われているサンプルの完全版は python-samples-vs-cpp-extension (GitHub) にあります。The completed sample from this walkthrough can be found on python-samples-vs-cpp-extension (GitHub).