====== Boost.Python - Boost Python Library ====== 本家: [[https://www.boost.org/doc/libs/release/libs/python/|Boost.Python - Boost Library Documentation]]\\ **Boost Python Library** は、Python と C++ を連携させるためのフレームワークである。Dave Abrahams の C++ コンパイラだけで、特別なツールを使用することなく、C++ クラスの関数やオブジェクトを Python に素早くシームレスに公開できる。\\ ===== Windows の Visual Studio での手順 ===== 以下は **Visual Studio** を利用して、**Python** からインポートできる **CPython** と **Boost.Python** で **C++ 拡張機能 (C++ extension)** を実装する方法の手順である。\\ ==== 前提条件 ==== [[python:python_install|Python のインストール]] が済んでいること。\\ [[windows:visualstudio|Visual Studio]] がインストール済みであること。\\ [[c_cpp:boost|Boost C++ Libraries]] がインストール済みであること。\\ ==== ソリューションと Python プロジェクト (PyHelloBoostPython) の作成 ==== Visual Studio を起動して、**「新しいプロジェクトの作成」**をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_001.png?600|Visual Studio 2019 Boost.Python 001}}\\ 言語: Python プラットフォーム: すべてのプラットフォーム プロジェクトの種類: コンソール を選択して、**「Python アプリケーション」**をクリックし **[次へ]** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_002.png?600|Visual Studio 2019 Boost.Python 002}}\\ 以下の内容で新しいプロジェクトを構成して **[作成]** をクリックする。\\ プロジェクト名: PyHelloBoostPython 場所: <任意のフォルダ> [v] ソリューションとプロジェクトを同じディレクトリに配置する {{c_cpp:visualstudio2019_boost.python_003.png?600|Visual Studio 2019 Boost.Python 003}}\\ **PyHelloBoostPython** ソリューションと **PyHelloBoostPython** プロジェクトが生成される。\\ {{c_cpp:visualstudio2019_boost.python_004.png?600|Visual Studio 2019 Boost.Python 004}}\\ **PyHelloBoostPython** プロジェクトの **Python 環境** を **Python 3.8** に設定する。\\ {{c_cpp:visualstudio2019_boost.python_009.png?200|Visual Studio 2019 Boost.Python 009}}\\ **Python 環境** を右クリックして **「すべての Python 環境を表示」** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_010.png?200|Visual Studio 2019 Boost.Python 010}}\\ **Python 2.7** が既定になっている場合は、**Python 3.8** を選択して **「これを新しいプロジェクトに対する既定の環境にする」** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_011.png?200|Visual Studio 2019 Boost.Python 011}}\\ これで **Python 3.8** が **「新しいプロジェクトに対する既定の環境です」**。\\ {{c_cpp:visualstudio2019_boost.python_012.png?200|Visual Studio 2019 Boost.Python 012}}\\ **ソリューション エクスプローラー** に戻り、**Python 環境** を展開して **Python 3.8** が配下にあることを確認する。\\ **PyHelloBoostPython** プロジェクトの **PyHelloBoostPython.py** ファイルに以下のコードを貼り付ける。\\ #!/usr/bin/env python # -*- coding: utf-8 -*- from itertools import islice from random import random import timeit from superfastcode_cpython import fast_tanh from superfastcode_boost import boost_tanh COUNT = 500000 # Change this value depending on the speed of your computer NUM_OF_EXEC = 30 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): # timeit monkey-patching timeit.template = """ def inner(_it, _timer{init}): {setup} _t0 = _timer() for _i in _it: retval = {stmt} _t1 = _timer() return _t1 - _t0, retval """ duration, result = timeit.timeit(lambda: fn(DATA), number=NUM_OF_EXEC) duration = duration / NUM_OF_EXEC print(f'{name} took {duration:.3f} seconds') for d in result: assert -1 <= d <= 1, " incorrect values" def main(): print(f'Running benchmarks with COUNT = {COUNT} x NUM_OF_EXEC = {NUM_OF_EXEC}') test(lambda d: [tanh(x) for x in d], '[tanh(x) for x in d] (Python implementation)') test(lambda d: [fast_tanh(x) for x in d], '[fast_tanh(x) for x in d] (CPython C++ implementation)') test(lambda d: [boost_tanh(x) for x in d], '[boost_tanh(x) for x in d] (Boost.Python C++ implementation)') if __name__ == "__main__": main() ==== CPython プロジェクト (superfastcode_cpython - Python 用 C++ 拡張機能) の作成 ==== **PyHelloBoostPython** ソリューションを右クリックして、**[追加] - [新しいプロジェクト...]** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_005.png?600|Visual Studio 2019 Boost.Python 005}}\\ 言語: C++ プラットフォーム: すべてのプラットフォーム プロジェクトの種類: コンソール を選択して、**「空のプロジェクト」**をクリックし **[次へ]** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_006.png?600|Visual Studio 2019 Boost.Python 006}}\\ 以下の内容で新しいプロジェクトを構成して **[作成]** をクリックする。\\ プロジェクト名: superfastcode_cpython 場所: <任意のフォルダ、もしくは、そのまま> {{c_cpp:visualstudio2019_boost.python_007.png?600|Visual Studio 2019 Boost.Python 007}}\\ **superfastcode_cpython** プロジェクトを右クリックして、**[追加] - [新しい項目...]** をクリックする。\\ 以下の内容で新しい項目を追加する。\\ 種類: C++ ファイル (.cpp) 名前: cpython_module.cpp 場所: そのまま {{c_cpp:visualstudio2019_boost.python_008.png?600|Visual Studio 2019 Boost.Python 008}}\\ **superfastcode_cpython** プロジェクトを右クリックして、**[プロパティ]** をクリックする。\\ 初期状態では、**構成: アクティブ(Debug)、プラットフォーム: Debug(Win32)** になっている。\\ {{c_cpp:visualstudio2019_boost.python_013.png?600|Visual Studio 2019 Boost.Python 013}}\\ 以下のように、**構成: すべての構成、プラットフォーム: すべてのプラットフォーム** に変更する。\\ これにより、**Debug、Release、Win32、x64** のすべての組み合わせについての設定を変更する。\\ **CPython プロジェクト** (Python 用 C++ 拡張機能) のビルドに必要な設定の概要は以下の通りである。\\ [構成プロパティ] - [全般] - [構成の種類]: ダイナミック ライブラリ (.dll) [構成プロパティ] - [詳細] - [ターゲット ファイルの拡張子]: .pyd [構成プロパティ] - [VC++ ディレクトリ] - [インクルード ディレクトリ]: Python 3.8 のインクルード ディレクトリ (C:\Python\include など) [構成プロパティ] - [VC++ ディレクトリ] - [ライブラリ ディレクトリ]: Python 3.8 のライブラリ ディレクトリ (C:\Python\libs など python38.lib の場所を指示) **[構成プロパティ] - [全般] - [構成の種類]** を **ダイナミック ライブラリ (.dll)** に設定する。\\ {{c_cpp:visualstudio2019_boost.python_014.png?600|Visual Studio 2019 Boost.Python 014}}\\ **[構成プロパティ] - [詳細] - [ターゲット ファイルの拡張子]** を **.pyd** に設定する。\\ {{c_cpp:visualstudio2019_boost.python_015.png?600|Visual Studio 2019 Boost.Python 015}}\\ **[構成プロパティ] - [VC++ ディレクトリ] - [インクルード ディレクトリ]** に **Python 3.8 のインクルード ディレクトリ** を追加する。\\ ※ここでは [[windows:scoop|Scoop]] でインストールした **Python 3.8** の設定を行っているが、各自の環境に合わせて設定すること。\\ $(USERPROFILE)\scoop\apps\python\current\include **※構成プロパティでは$(USERPROFILE)と指定しなければならない。コマンドプロンプトのように%USERPROFILE%と指定すると IntelliSense が正常動作しないようである。** {{c_cpp:visualstudio2019_boost.python_016.png?600|Visual Studio 2019 Boost.Python 016}}\\ **[構成プロパティ] - [VC++ ディレクトリ] - [ライブラリ ディレクトリ]** に **Python 3.8 のライブラリ ディレクトリ** を追加する。(**python38.lib**(Release ビルド時。Debug ビルド時は python38_d.lib が必要。) が存在するディレクトリを指定)\\ ※ここでは [[windows:scoop|Scoop]] でインストールした **Python 3.8** の設定を行っているが、各自の環境に合わせて設定すること。\\ $(USERPROFILE)\scoop\apps\python\current\libs **※構成プロパティでは$(USERPROFILE)と指定しなければならない。コマンドプロンプトのように%USERPROFILE%と指定すると IntelliSense が正常動作しないようである。** {{c_cpp:visualstudio2019_boost.python_017.png?600|Visual Studio 2019 Boost.Python 017}}\\ 上記のすべての設定が終わったら、プロジェクトのプロパティ ページの **[OK]** をクリックする。\\ **superfastcode_cpython** プロジェクトの **cpython_module.cpp** ファイルに以下の内容を貼り付ける。\\ #include #include #include 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); } PyObject* tanh_impl_cpy(PyObject*, PyObject* o) { double x = PyFloat_AsDouble(o); double tanh_x = tanh_impl(x); return PyFloat_FromDouble(tanh_x); } 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_cpy, METH_O, nullptr }, // Terminate the array with an object containing nulls. { nullptr, nullptr, 0, nullptr } }; static PyModuleDef superfastcode_module = { PyModuleDef_HEAD_INIT, "superfastcode_cpython", // 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 }; PyMODINIT_FUNC PyInit_superfastcode_cpython() { return PyModule_Create(&superfastcode_module); } ==== Boost.Python プロジェクト (superfastcode_boost - Python 用 C++ 拡張機能) の作成 ==== **PyHelloBoostPython** ソリューションを右クリックして、**[追加] - [新しいプロジェクト...]** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_005.png?600|Visual Studio 2019 Boost.Python 005}}\\ 言語: C++ プラットフォーム: すべてのプラットフォーム プロジェクトの種類: コンソール を選択して、**「空のプロジェクト」**をクリックし **[次へ]** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_006.png?600|Visual Studio 2019 Boost.Python 006}}\\ 以下の内容で新しいプロジェクトを構成して **[作成]** をクリックする。\\ プロジェクト名: superfastcode_boost 場所: <任意のフォルダ、もしくは、そのまま> {{c_cpp:visualstudio2019_boost.python_018.png?600|Visual Studio 2019 Boost.Python 018}}\\ **superfastcode_boost** プロジェクトを右クリックして、**[追加] - [新しい項目...]** をクリックする。\\ 以下の内容で新しい項目を追加する。\\ 種類: C++ ファイル (.cpp) 名前: boost_module.cpp 場所: そのまま {{c_cpp:visualstudio2019_boost.python_019.png?600|Visual Studio 2019 Boost.Python 019}}\\ **superfastcode_boost** プロジェクトを右クリックして、**[プロパティ]** をクリックする。\\ **構成: すべての構成、プラットフォーム: すべてのプラットフォーム** について設定する。\\ これにより、**Debug、Release、Win32、x64** のすべての組み合わせについての設定を変更する。\\ **Boost.Python プロジェクト** (Python 用 C++ 拡張機能) のビルドに必要な設定の概要は以下の通りである。\\ [構成プロパティ] - [全般] - [構成の種類]: ダイナミック ライブラリ (.dll) [構成プロパティ] - [詳細] - [ターゲット ファイルの拡張子]: .pyd [構成プロパティ] - [VC++ ディレクトリ] - [インクルード ディレクトリ]: Python 3.8 のインクルード ディレクトリ (C:\Python\include など) [構成プロパティ] - [VC++ ディレクトリ] - [ライブラリ ディレクトリ]: Python 3.8 のライブラリ ディレクトリ (C:\Python\libs など python38.lib の場所を指示) **[構成プロパティ] - [全般] - [構成の種類]** を **ダイナミック ライブラリ (.dll)** に設定する。\\ {{c_cpp:visualstudio2019_boost.python_020.png?600|Visual Studio 2019 Boost.Python 020}}\\ **[構成プロパティ] - [詳細] - [ターゲット ファイルの拡張子]** を **.pyd** に設定する。\\ {{c_cpp:visualstudio2019_boost.python_021.png?600|Visual Studio 2019 Boost.Python 021}}\\ **[構成プロパティ] - [VC++ ディレクトリ] - [インクルード ディレクトリ]** に **Python 3.8 のインクルード ディレクトリ** を追加する。\\ ※ここでは [[windows:scoop|Scoop]] でインストールした **Python 3.8** の設定を行っているが、各自の環境に合わせて設定すること。\\ $(USERPROFILE)\scoop\apps\python\current\include **※構成プロパティでは$(USERPROFILE)と指定しなければならない。コマンドプロンプトのように%USERPROFILE%と指定すると IntelliSense が正常動作しないようである。** {{c_cpp:visualstudio2019_boost.python_022.png?600|Visual Studio 2019 Boost.Python 022}}\\ **[構成プロパティ] - [VC++ ディレクトリ] - [ライブラリ ディレクトリ]** に **Python 3.8 のライブラリ ディレクトリ** を追加する。(**python38.lib**(Release ビルド時。Debug ビルド時は python38_d.lib が必要。) が存在するディレクトリを指定)\\ ※ここでは [[windows:scoop|Scoop]] でインストールした **Python 3.8** の設定を行っているが、各自の環境に合わせて設定すること。\\ $(USERPROFILE)\scoop\apps\python\current\libs **※構成プロパティでは$(USERPROFILE)と指定しなければならない。コマンドプロンプトのように%USERPROFILE%と指定すると IntelliSense が正常動作しないようである。** {{c_cpp:visualstudio2019_boost.python_023.png?600|Visual Studio 2019 Boost.Python 023}}\\ 上記のすべての設定が終わったら、プロジェクトのプロパティ ページの **[OK]** をクリックする。\\ **superfastcode_boost** プロジェクトの **boost_module.cpp** ファイルに以下の内容を貼り付ける。\\ #include #include #include 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); } BOOST_PYTHON_MODULE(superfastcode_boost) { using namespace boost::python; def("boost_tanh", tanh_impl); } ==== ソリューションの設定 ==== **ソリューション エクスプローラー** より **PyHelloBoostPython** ソリューションを右クリックして、**[構成マネージャー...]**をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_024.png?250|Visual Studio 2019 Boost.Python 024}}\\ **アクティブ ソリューション構成: Debug** に変更して、以下のプロジェクトが **Release ビルド**、**x64 プラットフォーム** でビルドされるように設定する。(標準では Python の **python38.lib (Release 版)** のみのため)\\ ^ プロジェクト ^ 構成 ^ プラットフォーム ^ ビルド ^ |superfastcode_boost |Release |x64 | [v] | |superfastcode_cpython |Release |x64 | [v] | **※必ず**ビルド**のチェックボックスをオンにすること。**\\ {{c_cpp:visualstudio2019_boost.python_025.png?600|Visual Studio 2019 Boost.Python 025}}\\ **アクティブ ソリューション構成: Release** に変更して、以下のプロジェクトが **Release ビルド**、**x64 プラットフォーム** でビルドされるように設定する。(標準では Python の **python38.lib (Release 版)** のみのため)\\ ^ プロジェクト ^ 構成 ^ プラットフォーム ^ ビルド ^ |superfastcode_boost |Release |x64 | [v] | |superfastcode_cpython |Release |x64 | [v] | **※必ず**ビルド**のチェックボックスをオンにすること。**\\ {{c_cpp:visualstudio2019_boost.python_026.png?600|Visual Studio 2019 Boost.Python 026}}\\ **ソリューション エクスプローラー** より **PyHelloBoostPython** ソリューションを右クリックして、**[プロパティ]**をクリックする。\\ **シングル スタートアップ プロジェクト**が **PyHelloBoostPython** であることを確認する。\\ {{c_cpp:visualstudio2019_boost.python_032.png?600|Visual Studio 2019 Boost.Python 032}}\\ ==== ソリューション内の Python プロジェクトで C++ 拡張機能 プロジェクトを参照する ==== **superfastcode_cpython**、および、**superfastcode_boost** プロジェクトの Python 用 C++ 拡張機能は、同一ソリューション内であってもそのままでは Python から import できない。\\ {{c_cpp:visualstudio2019_boost.python_027.png?610|Visual Studio 2019 Boost.Python 027}}\\ **PyHelloBoostPython** プロジェクトの**[参照]**を右クリックして、**[参照の追加...]**をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_028.png?250|Visual Studio 2019 Boost.Python 028}}\\ **superfastcode_cpython**、および、**superfastcode_boost** プロジェクトのチェックボックスをオンにして **[OK]** をクリックする。\\ {{c_cpp:visualstudio2019_boost.python_029.png?600|Visual Studio 2019 Boost.Python 029}}\\ 以下のように **PyHelloBoostPython** プロジェクトの参照に C++ 拡張機能 プロジェクトが追加されて、検索パス (**x64\Release**) にビルド出力の ***.pyd** ファイルが配置されるので Python プロジェクトから **import** することが可能になる。\\ {{c_cpp:visualstudio2019_boost.python_030.png?250|Visual Studio 2019 Boost.Python 030}}\\ ==== Python プロジェクトの実行 ==== Visual Studio の画面で **Ctrl + F5**(デバッグなしで開始) キーを押して実行する。\\ Python コードと C++ コードの実行速度のベンチマーク結果が表示される。\\ Running benchmarks with COUNT = 500000 x NUM_OF_EXEC = 30 [tanh(x) for x in d] (Python implementation) took 1.930 seconds [fast_tanh(x) for x in d] (CPython C++ implementation) took 0.248 seconds [boost_tanh(x) for x in d] (Boost.Python C++ implementation) took 0.289 seconds 続行するには何かキーを押してください . . . ===== 参考文献 ===== [[https://docs.microsoft.com/ja-jp/visualstudio/python/working-with-c-cpp-python-in-visual-studio?view=vs-2019|Python 用の C++ 拡張機能の記述 - Visual Studio | Microsoft Docs]]\\ [[http://moriyoshi.hatenablog.com/entry/20091214/1260779899|Boost.Python の機能をざっと紹介してみる - moriyoshiの日記]]\\ [[http://alpha.osdn.jp/devel/boost.python_ja.pdf|Boost.Python - Alpha]]\\ [[https://qiita.com/maiueo/items/b2093ba78cde988bb111|ctypesの変数についてのメモ - Qiita]]\\ [[https://docs.python.org/ja/3/library/ctypes.html|ctypes --- Pythonのための外部関数ライブラリ — Python 3.8.6rc1 ドキュメント]]\\ [[https://stackoverflow.com/questions/16105539/boost-python-custom-converter|c++ - Boost.Python custom converter - Stack Overflow]]\\