VC++ 2017 で Python モジュールを作る

Python、めちゃくちゃ便利ですね。私も遅まきながら、Python の持つパワーに目覚め始めました。

しかし、その実行速度が気になる場面もあります。Python を取り巻くライブラリ群がそうであるように、どうしても速度が欲しいところはピンポイントで C++ で書きたい。

そこで、Visual Studio 2017 の C++ を使って Python モジュールをビルドするまでの、環境の作り方についてまとめました。

pybind11 がおすすめ

C++ で Python モジュールを作ることを考えたとき、おおむね次の2つの選択肢があるようです。

  • Boost.Python
  • pybind11

しかし Visual Studio を使うなら、Boost.Python はおすすめしません。なぜかというと、Visual Studio 向けに配布されている NuGet パッケージ(DLL)にバグがあり、結局ビルドが通らないからです。

これは Python3 固有の問題のようで、次のフォーラムで議論されています(この記事の執筆時点では、未解決です)。

https://github.com/boostorg/python/issues/129

私はこの問題に半日悩まされた挙句、あきらめて pybind11 に切り替えたら10分でビルドが通りました。pybind11、マジおすすめです。

手順

Python から C++ のコードを呼び出すには、まず C++ のコードを DLL 化しなければなりません。ここではそれを作成するための手順を説明します。

1. Python を入手する

ここの手順は割愛します。私は Anaconda3 を使いました。

2. pybind11 のヘッダファイル群を入手する

GitHub にコミットされているファイルをダウンロードします。必要なのはこのうち include/pybind11 以下だけです。

https://github.com/pybind/pybind11/

3. Visual Studio のプロジェクトを作る

「空のプロジェクト」で構いません。ここで付けた名前が Python の import 宣言になりますから、名前は小文字で始めたほうがよいでしょう。

4. 構成プロパティを変更する

プロジェクトの「構成の種類」を .dll に、「ターゲットの拡張子」を .pyd に変更します。

5. パスを通す

プロジェクトのパスの設定を追加します。

Python のインストール先に付属のヘッダとライブラリがあるはずですから、それに応じて適切に「追加のインクルードディレクトリ」と「追加のライブラリディレクトリ」を入力してください。

私の場合は、こうなりました。


6. マクロを追加する

pybind11 はセキュアでない関数 sscanf を使っているため、そのままではビルドが通りません。セキュアでない関数の使用を許容するオプション _CRT_SECURE_NO_WARNINGS を、「プリプロセッサの定義」に追加します。

7. ビルドする

C++ を使って、高速でクールなコードを書いてください。手順2 で入手したヘッダファイル群は、ここで使います。

試しに、Python 側から呼び出したい関数とクラスを定義する、C++ のコードを書いてみます。

下のほうにある PYBIND11_MODULE 以下の記述は、Python 側にモジュールの情報を伝播するためのおまじないです。この記述ルールは次の URL にまとまっていますので、詳しくはこれを参照してください。

https://pybind11.readthedocs.io/

使ってみる

上のコードをビルドすると、拡張子が .pyd のライブラリができますから、これを Python コードと同じ場所に置いて、実際に使ってみましょう。

呼び出す側の Python コードは、たとえばこのようになります。

実行結果はこのようになりました。

ちゃんと連携できています。Python のリストと C++ のベクタの相性もばっちりですね。

ソフトウェアの設計・実装がうまく行かなくてお困りではありませんか? 組込屋にお任せください。リモート案件は、常駐の半額でお受けしています。

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)