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

  • 2022年9月24日
  • 2022年9月24日
  • Python
  • 298View
  • 0件

はじめに

Python から C++ のメソッドを呼び出すためには、いくつかの手段があります。
本記事では swig を利用して C++ メソッドを呼び出す手法を紹介します。

swig とは、C++ のヘッダファイルを解析して、これに基づいてラッパーとなるコードを自動生成するための仕組みになります。
おおよそ次のような流れになります。

  1. Python から呼び出すための C++ ソースファイル、ヘッダファイルを用意する。
  2. swig のインタフェースファイルを用意し、ここから C++ ヘッダファイルを参照する。
  3. swig を実行して、C++ ラッパーコード、Python ラッパーコードを生成する。
  4. g++ を実行して、C++ ソースファイル、C++ ラッパーコードから動的リンクライブラリを生成する。
  5. Python ラッパーコードを介して、C++ メソッドを呼び出す。

動作環境

  • Windows 11
  • WSL Ubuntu 20.04
  • g++ 9.4.0
  • swig 4.0.1
  • python 3.8.10

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

事前準備

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

$ sudo apt update
$ sudo apt upgrade

swig をインストールします。

$ sudo apt install swig

-veresion オプションを指定して swig を実行するとバージョンを確認することができます。
4.0.1 の swig がインストールされました。

$ swig -version

SWIG Version 4.0.1

Compiled with g++ [x86_64-pc-linux-gnu]

Configured options: +pcre

Please see http://www.swig.org for reporting bugs and further information

C++ コードのコンパイルのため、g++ もインストールしておきます。

$ sudo apt install g++

C++ ソースコード

Python から呼び出すための C++ ソースコードを準備します。

#ifndef HELLO_H_
#define HELLO_H_

void hello();

#endif  // HELLO_H_
#include "hello.h"

#include <cstdio>

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

hello メソッドを Python から呼び出します。
swig に読み込ませるため、hello メソッドを前方定義したヘッダファイル hello.h も準備します。

swig インタフェースファイル

ラッパーコードを生成するための swig インタフェースファイル hello.i も用意します。

%module hello_ext

%{
#include "hello.h"
%}

%include "hello.h"

hello.i をインプットに swig を実行することで、ラッパーファイルが2つ (hello_ext.pyhello_wrap.cc)生成されます。

$ swig -c++ -python -cppext cc hello.i
$ ls hello_ext.py hello_wrap.cc
hello_ext.py  hello_wrap.cc

動的リンクライブラリの生成

hello.cchello_wrap.cc をインプットとして、動的リンクライブラリを生成します。

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

.so ファイルは hello_ext.py を介して呼び出されます。
今回のケースでは動的リンクライブラリのファイル名を _hello_ext.so とする必要があります。

Python から hello メソッドの呼び出し

ここまでできたら Python からの呼び出しは簡単です。
hello_ext をインポートして、hello メソッドを実行します。

import hello_ext

hello_ext.hello()
$ python3 main.py
Hello, world!

なお、hello_ext.py_hello_ext.so の2ファイルは、main.py と同じディレクトリに配置する必要があります。