[Python][WSL] Boost Python で C++ メソッドを呼び出す

  • 2022年9月23日
  • 2022年9月24日
  • Python
  • 5View
  • 0件

はじめに

Python から C++ メソッドを呼び出す手段の一つとして Boost Python の利用があります。
WSL Ubuntu 上にて、Boost Python を利用するための手順を紹介します。

Boost の公式ドキュメントはこちらから参照可能です。

動作環境

  • Windows 11
  • WSL Ubuntu 20.04
  • g++ 9.4.0
  • boost 1.71.0
  • python 3.8.10

Boost Python で C++ メソッドを呼び出し

事前準備

初めに、Ubuntu パッケージを最新化しておきます。

$ sudo apt update
$ sudo apt upgrade

C++ コードをコンパイルするため、Ubuntu に g++ をインストールします。

$ sudo apt install g++

また、Boost Python を利用してコンパイルするための関連パッケージをインストールします。
libboost-python-dev をインストールすることで、必要なものはまとめてインストールされます。

$ sudo apt install libboost-python-dev

おおよそ次のようなパッケージが主に関連します。

依存パッケージインストールされるファイル
libboost1.71-dev/usr/include/boost/python.hpp
libpython3.8-dev/usr/include/python3.8/pyconfig.h
libboost-python1.71.0/usr/lib/x86_64-linux-gnu/libboost_python38.so.1.71.0

C++ コードから動的リンクライブラリ生成

Python から呼び出されるソースコードです。

#include <boost/python.hpp>

void hello()
{
    printf("Hello, world!\n");
}

BOOST_PYTHON_MODULE(hello_ext)
{
    boost::python::def("hello", hello);
}

単純な標準出力をするのみの hello メソッドを Python へエクスポートします。
BOOST_PYTHON_MODULE のブロックは、エクスポート方法を定義するための記述になります。

ソースコードを用意したら、g++ コマンドで動的リンクファイルを生成します。
なお、BOOST_PYTHON_MODULE で指定するモジュール名 hello_ext と、出力ファイル名 hello_ext.so は一致させる必要があります。

$ g++ -fPIC --shared hello.cc -o hello_ext.so -I/usr/include/python3.8 -lboost_python38
$ ls hello_ext.so
hello_ext.so

Python コードから hello 呼び出し

Python コードは簡単です。
hello_ext をインポートして、hello_ext.hello を呼び出すのみです。
なお、先ほど生成した hello_ext.so ファイルは、main.py と同じディレクトリに配置しておきます。

import hello_ext

hello_ext.hello()

Boost Python が多くの部分を隠蔽してくれているため、シンプルな記述で呼び出すことができます。

$ python3 main.py
Hello, world!

注意点

g++ コマンドを実行する際には、引数の順番が重要です。
インプットファイル(hello.cc)は -lboost_python38 のオプションよりも前に指定する必要があるようです。

例えば次のように、hello.cc を末尾に持ってきてしまうと、boost_python38 のリンクがスキップされてしまうようです。

$ g++ -fPIC --shared -o hello_ext.so -I/usr/include/python3.8 -lboost_python38 hello.cc

これで生成された hello_ext.so を呼び出そうとすると、メソッドの探索エラーが発生してしまいます。

$ python3 main.py
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    import hello_ext
ImportError: /home/***/hello_ext.so: undefined symbol: _ZNK5boost6python7objects21py_function_impl_base9max_arityEv