こんにちは。情熱開発課の青柳です。
今回はC++でのホットリロードが出来るようなライブラリ、ツールを軽く試してみました。
軽く試す、という事で実際にプロジェクトで使う、という事ではなくサンプルを実行する、というだけにします。
ホットリロードを実装しました!実際に業務で使いました!
という話では残念ながらありません、ご了承ください、、、。
また環境は全てWindows/VisualStudioでの動作になります。
C++でのホットリロードとは?
一言でいえばプログラム実行時にソースコードの編集を反映させること、となります。
通常、C++という言語ではソースコードを書き、コンパイル、リンクを行って実行可能バイナリを作成して、プログラムが実行されます。
変更したい場合は、一旦プログラムの実行を止めてから、ソースコードを変更し、コンパイル、リンクを行い再度実行可能バイナリを作成して実行。
というサイクルを回していきます。
ホットリロードは、プログラムを動かしたままソースコードを変更しコンパイル、リンクして実行中のプログラムへ反映させる、という事です。黒魔術です。
Youtubeの動画で実例をご覧ください(40秒当たりからソースを編集して反映されます)
どうやってやっているの?
黒魔術です、、、と自分が理解していないことがばれてしまうのですが
日本語で詳しい解説を書いて頂いているサイトがありますので
そちらのリンクを貼らせて代えさせて頂きます。
[dynamic obj loader / primitive: blog 2012-09-04]
http://i-saint.hatenablog.com/entry/2012/09/04/223007
ただすべての変更が反映できるわけではなく仮想関数自体の追加などは難しい面があるようです
どんなライブラリ、ツールがあるの?
自分が調べたところだと以下の4つがありました
RuntimeCompiledCPlusPlus
DynamicPatcher
blink
UE4の機能でのホットリロード
今回はRCCPPとblinkを動かしてみました。
RuntimeCompiledCPlusPlus
MasterブランチにSimpleTestがあるので GitHubから落とし、そちらで試してみます。
ソリューションを開くとRuntimeCompilerとRuntimeObjectSystemのプロジェクトが確認できます。こちらが処理の肝になっているようです。
次にGameObject.cppを覗いてみます。
Serializeメソッドがあり中でなにかマクロでメンバ変数を囲ってますね。
RCCPPの為の記述な感じがします。
また、Environment.cppでRuntimeObjectSystemのNewをしています。
実行時に編集を感知しコンパイルするにはここら辺が必要という事ですね。
ともあれ実行してソースを編集すると画像のようにコンパイルされて動作が変わります。
試すだけならタダですのでぜひ試してみてください。魔法、、、と思うはずです。
他にもImguiで使うサンプルなどありますが
#include "RuntimeSourceDependency.h"
RUNTIME_COMPILER_SOURCEDEPENDENCY_FILE( "imgui/imgui", ".cpp" );
RUNTIME_COMPILER_SOURCEDEPENDENCY_FILE( "imgui/imgui_widgets", ".cpp" );
RUNTIME_COMPILER_SOURCEDEPENDENCY_FILE( "imgui/imgui_draw", ".cpp" );
RUNTIME_COMPILER_SOURCEDEPENDENCY_FILE( "imgui/imgui_demo", ".cpp" );
こんな感じにソースの場所を指定したり、 RuntimeObjectSystem はNewしたりとなかなか導入には苦労しそうな感じがあります。
blink
次はblinkを使ってみます。
ReadMeを読んでみるとこれは
blink.exe (対象の実行ファイル).exe
でホットリロードが実現できるようです。そんなに簡単でいいの?
という事でやりましたー
出来る、出来るぞ!?
という事で出来ましたがこちらは制限が結構きついようで、virtualの付いたメソッドは反映ができないようでした。
でもこんなに手軽にホットリロードが出来るなんて夢のようです。
こちらもぜひ試して頂ければと思います。
注意点としてblinkと対象のExeのアーキテクチャは合わせる必要があります。
x64ならx64同士、x86ならx86同士の必要があります。
終わりに
導入には一癖ありそうで敬遠していたホットリロードですが、blinkの手軽さには驚きました。
元々、変更がありそうな部分は外部パラメータ化したり、別途Script言語を作ってそれを実行させる形にしたりする場合が多くホットリロードがないと困るという事はあまりないかなと思っていました。
ただ最近Imguiを使っていてちょっとホットリロードしたいなと思ったのが今回のきっかけでした。
ここまで手軽ならイテレーションを速く回す為の一つの方法としてはいい場合がありそうです。
また、黒魔術の中身には興味深いものがたくさんありますね。
別の方法、ライブラリ、ツールがありましたら教えて頂けると幸いです。
(機能と手軽さならDynamicPatchなのではと思いつつ、動かすのにちょっと苦労しそうでしたので今回は外させて頂きました)
【免責事項】
本サイトでの情報を利用することによる損害等に対し、
株式会社ロジカルビートは一切の責任を負いません。