はじめに
ゲームの根幹部分の実装はOpenGLやDirectX、winAPIを使用してC/C++で実装するのが一般的ですが、メモリの手動で管理しなければならないので難しいです。そこでゲームエンジンやツクール系、自分でデータを作れるフリーゲームでは独自の構文を実装したり、ほかの簡単なプログラミング言語で書けるようになっています。今回は自作のゲームエンジン(?)用にPythonで構文を記述できるようなシステム実装していきます。
何をしたいのですか
まずゲームエンジンの構文として使いたいのでextend(拡張)ではなくembed(埋め込み)にて実装します。要するにCppに埋め込んで実行するということですね。こうすることでPython側の記述に応じてCpp側でうまく処理することができます。
そしてPython側で実装した敵やアイテム、オブジェクトの情報をCpp側のプログラムに渡します。また、フラグ管理や、敵の動きを制御するために現在のオブジェクトの状態やプレイヤーの位置、アイテムの有無などを処理するためにCppの関数をPythonにextend(拡張)します。
CppからPythonを使う方法
Pythonの実装は様々でJPythonというPythonをJavaに書き換えて実行するものだったり、PyPyという興味深い名前の実装は、JITコンパイルで機械語に翻訳して動くものです。一応これが軽く調べた限りでは実行速度が現状最速クラスのようです。
だったりいろいろありますが、公式ページからダウンローでできる公式の実装はCPythonというもので、C言語に変換して実行するものになります。このシステムを使ってPython/C APIというものが公式で公開されており、その名の通りPythonとC系を相互利用できるというものです。
APIは習得に時間がかかりそうなので今回はライブラリを使って楽をします。代表的なのとしてPyBind11やctypesなどたくさんありますが今回はBoost.Pythonを使用します。
Boost.Pythonとは
Boost.PythonとはBoostライブラリいうライブラリの一部です。BoostライブラリはおそらくCppにおいて最も有名なライブラリといっても過言ではなく、実質標準ライブラリと化しています。一部機能は標準ライブラリに組み込まれています(threadやlandomなど)。Boostにはほかにも便利なライブラリがたくさんあり、jsonファイルの読み込みなどにも対応していて非常に便利です。
Boost.Pythonは、後発のPythonとCを相互利用するライブラリなので、ほかのライブラリと比較して簡単に記述することができます。最も簡単に記述できるのはPyBindだそうですが、ほかにも便利な機能のあるこちらを選びました。ということでさっさと片付けていきましょう!!
は?
ということで、めちゃくちゃ簡単に使えると思ったらとても難しかったです。
まず、情報が少なかったです。いやないことはないんですけど、ほとんどがLinuxやMacなどのUnix系でWindowsの情報は全くと言っていいほどありませんでした(ということで珍しく記事を書いている)。
あと、Pythonに関してある程度勉強しておいた方がいいと思います。特にimportについてです。まあ、Includeと変わらないんですけど全く一緒というわけではないので、ちょっと苦労しましたね。
結局どこがわからなかったの?
ぶっちゃけ埋め込みは比較的簡単でしたが、拡張が死ぬほど難しかったです。まあ、全体的に意味わからなかったですというか情報がない。
1. Boost.Pythonの静的リンクファイルがない
おそらく一番上に出てくるであろう
b2.exe install -j2 --prefix=(インストールしたいディレクトリ)
boostjpより引用
だとインストールできるんですが、Boost.Pythonのライブラリファイルがうまくインストールされません。これに対処するためにb2コンパイラ(Makeに近い)を勉強する必要があるのですが...めんどくさかったので以下の記事を参考にやったらうまくいきました。感謝!!!
2. pyconfig.hがインクルードできません
boostのインクルードディレクトリだけを指定するとこうなります。Boost.Pythonは先ほど軽く話しましたがPython/C APIというものを使っています。ですからそこのディレクトリも指定しないといけないということですね。Pythonをデフォルトの設定でインストールした場合は
C:\Users\ユーザー(メイン)\AppData\Programs\Python
にありました。カスタムインストールの場合は知りませんが、これかなりわかりにくいと思います。なんだよProgramsフォルダって
3. 何ファイルを生成すればいいのか
ぶっちゃけ今までの問題は調べれば何とかなってました。が今回は1筋縄ではいかず、1日悩んでも全く成果が出ずもやもやしながらCopilotを叩いてたらなんかうまくいったんですよね。
Boost.Pythonのチュートリアルでは「b2使ってないやつはビルドうまくいっていないからこれ使え」という記述があったのでその通りにやったら1日悩んでもビルドできませんでした。Boost.Jam言語情報が少なすぎですね。
結局、無理やりb2のコマンドラインで無理やり実行して無事に通ったんですけど、うまくリンクできず...
じゃあどうすればいいのと聞いたところ.dll拡張子を.pydに変更すればいいそうです。で、実際にやったら通りました。「拡張子変えるとか絶対違うだろ」ってずっと思ってましたが、これが正解のようです(詳しくはこちら)。結論として、生成したdllファイルをpydファイルに変更すればいいので別にb2いらなかったって言うねハハハ...
Boost.Pythonのビルドまとめ
散発的に書きなぐりましたが、整理するとこんな感じです
- BoostのディレクトリとCPythonのディレクトリを設定
- コンパイル設定をdllにしてビルド
- 拡張子をdllからpydに(案の定警告が出るが無視する)
- インポートするディレクトリを設定(後述)
図示するとこんな感じ
ソースファイルが関数やクラスの実装ファイルで、ラッパファイルがPython向けにラップする(後述)するものでそれらを組み合わせて共有ライブラリ(.dll)を生成し、それをパイソン用共有ライブラリ(.pyd)に変換してパスを設定してインポートするということですね。
#2へ続く
参考にしたサイト