LoginSignup
7
7

More than 3 years have passed since last update.

Pybind11でC++関数をPythonから実行する(Windows & Visual Studio Codeな人向けの環境構築)

Last updated at Posted at 2020-06-04

(2021年1月追記)
以下の記事ではg++を使った環境構築・ビルド方法を説明していますが、msvcを使った環境構築・ビルド方法およびデバッグ方法の記事を投稿しましたのでそちらをご覧ください。g++を使ったデバッグはブレークポイントで止められなかったのであきらめましたorz


Pybind11を使ってC++の関数をPythonから呼び出せるようにする環境を構築する方法を説明します。WindowsかつVisual Studio Codeを使っている人向けの記事があまりなかったので、いろいろ調べたことをまとめておきます。ただ、エディターはVisual Studio Codeでなくても大丈夫です。

0. 環境

以下の環境で確認しています。CMake以下のインストール方法はこの記事で説明します。

  • OS: Windows 10
  • エディター: Visual Studio Code
  • Python: 3.7 (Anaconda 3 2019.7)
  • この記事でインストールするもの
    • CMake: 3.17.2
    • Mingw-w64: x86_64-8.1.0-posix-seh-rt_v6-rev0
    • pybind11: 2.5.0

1. 環境構築

1.1. CMakeのインストール

CMakeとは、C++等をビルドする際の設定を様々なコンパイラーで利用できるようにするツールです。が、私自身よく分かっていないので、詳しくはこちらをみてください。

ダウンロード ページからWindows win64-x64 Installerをダウンロードし、インストールします。

1.2. Mingw-w64のインストール

Mingw-w64とは、フリーのC++コンパイラg++のWindwos 64bit版です。これも私自身よく分かっていないので、グーグル先生に聞いてみてください。

ダウンロードページからインストーラー等をダウンロードします。オンライン環境であれば、インストーラーMinGW-W64-install.exeをダウンロードしインストールします。オフライン環境であれば、7z形式のファイルをダウンロードして展開します。

以下、この記事ではg++.exeの配置が次のようになっているとします:D:\UserProgram\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin\g++.exe

次に、上記フォルダーを環境変数Pathに追加します。Powershellで追加するには、

ユーザー単位
> $envPath = [System.Environment]::GetEnvironmentVariable("Path", "User")
> $envPath += ";D:\UserProgram\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin" #←g++.exeが含まれているパス
> [System.Environment]::SetEnvironmentVariable("Path", $envPath, "User")

端末単位で設定するには1行目と3行目の"User""Macine"に置き換えます。この場合、管理者権限が必要になります。

端末単位(要管理者権限)
> $envPath = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
> $envPath += ";D:\UserProgram\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin" #←g++.exeが含まれているパス
> [System.Environment]::SetEnvironmentVariable("Path", $envPath, "Machine")

1.3. Pybind11のインストール

オンライン環境なら、pipでインストールします。

Powershell
> pip install pybind11

オフライン環境の場合は、
PyPIのダウンロード ページからpybind11-x.y.z-py2.py3-none-any.wh(x, y, zは数字)をダウンロードしてから、pipでインストールします。

Powershell
> pip install ダウンロード先/pybind11-2.5.0-py2.py3-none-any.whl  #2.5.0部分は適宜読み替え 

後で使うので、公式のサンプルもダウンロードします。オンライン環境(かつGitをインストール済み)なら、Powershell上でダウンロードしたい場所まで移動し、

Powershell
git clone --recursive https://github.com/pybind/cmake_example.git

としてダウンロードします。オフライン環境の場合は、公式のサンプルClone or downloadボタンを押します。また、pybind11フォルダーも同様にダウンロードします。

【重要】cmake_example/pybind11/include/pybind11以下のファイルを、C:\ProgramData\Anaconda3\include\pybind11以下のファイルで置き換えます。置き換える前のファイルは古いみたいで、コンパイルは通りますが、warning: 'void PyThread_delete_key_value(int)' is deprecated [-Wdeprecated-declarations]というワーニングが大量に出ます。(2021/1修正。現時点ではワーニングが出ないため削除。)

2. やってみるさ( ■ 一 ■)

先ほどダウンロードしたcmake_exmpleフォルダーから、pybind11srcCMakeLists.txtを適当なフォルダー(以下、project_rootとします)にコピーします。なお、パス名に日本語が含まれるとConfigureとGenarateができないため、半角英数字(スペースと記号もOK)にしてください。

フォルダー構成
project_root
├ pybind11
│ ├ docs
│ ├ include
│ │ └pybind11   
│ │  └・・・    
│ └・・・
├ src
│ └main.cpp
└ CMakeLists.txt

コンパイル エラー(なぜかはわからない)になるため、main.cpp#ifdef VERSION_INFO#endif部分をコメントアウトor削除。

project_root/src/main.cpp
#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

namespace py = pybind11;

PYBIND11_MODULE(cmake_example, m) {
    ()
    m.def("add", &add, R"pbdoc(
        Add two numbers

        Some other explanation about the add function.
    )pbdoc");
   ()
//コンパイルエラー(なぜかはわからない)になるので以下をコメントアウトor削除
//#ifdef VERSION_INFO
//    m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO);
//#else
//    m.attr("__version__") = "dev";
//#endif
}
project_root/CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(cmake_example)

add_subdirectory(pybind11)
pybind11_add_module(cmake_example src/main.cpp)

project_rootをVisual Studio Codeで開き、Ctrl+@ でターミナルに移動し、以下を実行します。

Powershell
> mkdir build                      # ビルド先のフォルダーを作成
> cd build                         # ビルド先に移動
> cmake -G "MinGW Makefiles" ..    # ConfigureとGenarate
> cmake --build .                  # ビルド

成功すれば、buildフォルダーにcmake_example.cp37-win_amd64.pydが作成されます。先ほどのターミナルで試してみましょう。

Powershell
> python           # Pythonを起動
>>> from cmake_example import add 
>>> add(1,2)
3
>>> exit()         # Powershellに戻る

add関数を呼び出せていれば成功です。

3. トラブルシューティング

3.1. ConfigureとGenarate

3.1.1. cmake -G "MinGW Makefiles" ..ができない

パス名に日本語が含まれるとConfigureとGenarateができません。パス名は大人しく半角英数字(スペースと記号もOK)にしましょう。日本語に対応して欲しいですね。

3.2. ビルド時

3.2.1. warning: 'void PyThread_delete_key_value(int)' is deprecated [-Wdeprecated-declarations]

上で書きましたが、cmake_example/pybind11/include/pybind11以下のファイルを、C:\ProgramData\Anaconda3\include\pybind11以下のファイルで置き換えます。置き換える前のファイルは古いみたいで、コンパイルは通りますが、warning: 'void PyThread_delete_key_value(int)' is deprecated [-Wdeprecated-declarations]というワーニングが大量に出ます。(2021/1修正。現時点ではワーニングが出ないため削除。)

3.2.2. error: '::hypot' has not been declared

2018年12月以前にリリースされたPythonの各バージョンを使っていると、このエラーでビルドが失敗します。原因はpyconfig.hで、次のように修正します。

Pythonインストール先/include/pyconfig.h
  #define COMPILER "[gcc]"
- #define hypot _hypot     ←この行を削除する。
  #define PY_LONG_LONG long long
  #define PY_LLONG_MIN LLONG_MIN
  #define PY_LLONG_MAX LLONG_MAX

この問題は公式でも議論されており、プルリクエスト後、マージされています(実際のコミット)。

4. おわりに

最後まで読んでいただき、ありがとうございます。
この記事では公式のサンプルを使っただけでしたが、他の人の記事を参考に、main.cppCMakeLists.txtを修正してみてください。
C++に疎いため、たったこれだけの事が出来るようになるまでに時間がかかりました。これからC++デビューしたいと思います。あと、VSCodeの拡張機能CMake Toolsの使い方もそのうち調べて記事にしたいです。

参考

以下の記事を参考にさせていただきました。

Mingw-w64のインストール方法

CMakeの解説

Pybind11の使い方

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7