LoginSignup
4

More than 1 year has passed since last update.

posted at

updated at

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

Pybind11を使ってC++の関数をPythonから呼び出せるようにする環境を構築する方法を説明します。WindowsかつVisual Studio Code(以下、VSCode)を使っている人向けの記事があまりなかったので、いろいろ調べたことをまとめておきます。
デバッグ編はこちら

0. 環境

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

  • OS: Windows 10 Home 20H2
  • エディター: Visual Studio Code 1.52.1
  • Python: 3.7 (Anaconda 3 2019.7)
  • この記事でインストールするもの
    • CMake: 3.19.2
    • msvc: 2019 Release
    • pybind11: 2.6.1

1. 環境構築

1.1. CMakeのインストール

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

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

また、VSCode用の拡張機能CMake ToolsもVSCodeにインストールしておきます。端末がオフラインの場合はこちらを参考にしてください。

1.2. msvcのインストール

msvcとは、Microsoft製C++コンパイラです。Visual StudioのC++コンパイラー部分です。

インストール方法は、端末がオンラインの場合はこちらを、オフラインの場合はこちらをご覧ください。

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

オフライン環境の場合は、cmake_exampleから、↓ Code ▾(緑色) -> Download ZIPでダウンロード、また、pybind11フォルダーが空になっているので、pybind11からも同様にダウンロードし、中身を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)にしてください。(コンパイラーにg++を使うと日本語はダメだけど、msvcならOKみたい)

フォルダー構成
project_root
├ 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 3.4...3.18)
project(cmake_example)

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

# EXAMPLE_VERSION_INFO is defined by setup.py and passed into the C++ code as a
# define (VERSION_INFO) here.
target_compile_definitions(cmake_example PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO})

project_rootをVSCodeで開き、コマンド パレット(Ctrl+p)からCMake Toolsを使ってビルドします。

  1. Cmake: Select a KitVisal Studio Build Tools 2019 Release - amd64を選択
  2. Cmake: Select VariantDebugを選択
  3. Cmake: Buildを実行

なお、上記はVSCodeのステータスバー(下部の青いバー)をクリックして設定することもできます。

成功すれば、./build/Debugフォルダーにcmake_example.cp37-win_amd64.pydが作成されます。VSCodeでCtrl+@でターミナルを開き、試してみましょう。

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

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

add関数のデバッグ方法はデバッグ編にて説明していますのでそちらもご覧ください。

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

3.1. ConfigureとGenarate

3.1.1 Unknown CMake command "pybind11_add_module".

pybind11フォルダーが空になっていませんか?git clone時に--recursiveオプションを付け忘れるか、zipダウンロードの場合はpybind11のダウンロード & 展開を忘れるとそのようになります。

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

パス名に日本語が含まれるとConfigureとGenarateができません。パス名は大人しく半角英数字(スペースと記号もOK)にしましょう。日本語に対応して欲しいですね。(コンパイラーにg++を使うと日本語はダメだけど、msvcならOKみたい)

3.2. ビルド時

3.2.1. 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

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

3.2.2. 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修正。現時点ではワーニングが出ないため削除。)

4. おわりに

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

参考

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

CMakeの解説

CMake Toolsの使い方

Pybind11の使い方

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
What you can do with signing up
4