====== 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]]\\