Extension

PeloReaper Extensionの情報やダウンロードはこちらからどうぞ。
PeloReaper Extension for REAPER is here.
ReaperBanner01_w250 AudioSoftBanner01_w250

C++ REAPER Extension (2) : DLL名でハマったお話

こんばんはぺろりです。
今回は前回の記事で触れた、DLL名でハマったもう一つのネタを紹介します(忘れないうちに)。

これは筆者のやり方がまずかったというだけなんですが(汗)、自作のExtensionのDLLをどこに置いてテストやデバッグをするかがポイントになります。
筆者はSWSにならって、REAPERのインストールフォルダにあるPluginsフォルダにDLLをコピーして実行&デバッグを行っていました。
(このあたりはSWSのプロジェクト設定(ビルドイベント)を見ると参考になります)

で、しばらくは特に何も問題ありませんでした。

突如問題になったのは、ActionListのいくつかのSectionにActionを追加してみようとしたところからです(今までは通常のMainセクションのみの登録ばかりでした)。
DLLのエントリポイントでActionをMIDIEditorセクションなどに登録しようとするのですが、これも問題なく成功します(ActionIDなどもREAPERから発行されるのをデバッガで確認済み)。
やったー、とREAPERがそのまま起動した後、ActionListでMIDIEditorセクションを見ると
「あれ・・・?」
さっき登録できたActionが一切登録されていない・・・

しばらくいろいろ試した後、同じことをSWSのプロジェクトでやってみると、うまく登録できてしまいました。
このへんでぺろりの頭もだいぶ混乱気味。

仕方がないので食パンを切ってピザトーストにして美味しくいただきました(ただの夕食)。
頭をクリアにしていろいろ筆者のDLLとSWSの何が違うのか検討していった結果、ピンと来ました。
「もしかして・・・実はまだファイル名の規則か何かをミスってるのか?」
試しにSWSと似たような名前(reaper_sws2.dllとか)に変えて試すとうまくいってしまいました。

ここでハッとして Pluginsフォルダを俯瞰してみたところ、
「もしや初期化順・・・!?」

当時自分で作っていたテスト用のDLLはreaper_dbg.dllとかてきとーなファイル名にしていたのですが、これがまずかったようです。
推測ですが、REAPERはプラグインDLLを名前の順に読み込んで初期化を行っている模様。
そして、自分のDLLをreaper_midi.dllよりも前になる名前にしてしまうと、DLLロード時にMIDIEditorセクションに登録したコマンドがreaper_midi.dllロード時に失われてしまうのではないかと。
実際、reaper_midi.dllより後ろになる名前(reaper_nnn.dllとか)にしてやったら問題なくMIDIEditorセクションへAction登録したものが残りました。
これでDLLの名前を変えることで、やっと問題を回避することが出来た訳です。

今回の件はREAPERインストールフォルダのPluginディレクトリにDLLを配置したことによる弊害なので、実はREAPERのリソースフォルダにあるUserPluginsにDLLを配置すれば問題ありませんでした。
(おそらくREAPERのPluginが全て初期化された後にUserPlugins側が読み込まれるのではないかと)

ただ、置き場所や名前に依存して動いたり動かなかったりするプログラムは気持ちが悪いので、あらかじめ今回の問題にひっかからないような名前にしておくのが良いかと思います。
ちなみに自分は"reaper_x"をDLL名のプレフィックスとして付けるようにしています。
(例えば reaper_xpelori.dll など)

ということで、今回はハマった事例の経緯をぐだぐだと説明してしまいましたが、これを見て皆さんはハマらないようにしてくださいね。

C++ REAPER Extension (1) : サンプルプログラム解説

今日は先日こちらで配布した、REAPER C++ Extensionのサンプルを例にポイントなどを書いておきます。
筆者はREAPERを使い始めてまずいきなりC++Extensionの作り方を調べる方向に行ってしまったのですが、どこから手を付けていいやらなにやらよくわからんやらで結構ハマりました。

■reaper_plugin_functions.h
このヘッダはどこからやってきたの?って感じですが、これはREAPER本体から書き出します。
メインメニューの[Actions > ActionList]から
・[developer] Write C++ API functions header
を実行すると、書き出し先を指定するダイアログが出るので、任意の場所に保存します。
この時に、[Write functions exported by 3rd party extensions]にチェックを入れると、3rdPartyの公開
してるAPIなんかもヘッダに書き出されます(当面は不要ですが)。
このあたりも自分でAPIを外部公開する方法があるのですがそれはどこかの機会にでも。
WriteCppHeaderAction
 ↑これを実行
SaveCppHeaderDlg
 ↑このウィンドウでヘッダを保存

■reaper_plugin.h
これはSWSのソースから拝借しました。
どうも公式のExtensionSDKより新しいもののようなのですが、これがどこから出てきたのか出自がよくわからないです・・・。
とはいえこのヘッダはExtensionを作る上で極めて有用な情報源となります。

■ReaperApiImpl.cpp
reaper_plugin_functions.h内にあるREAPERAPI_LoadAPI()の実体を生成するためのファイルです。
自分でAPIを一つずつロードしていく実装はSWSなどでも行われていますが、この関数でAPIを呼び出す準備を大幅に簡略化できるので助かります。

■reaper_HelloAction.cpp
ここではDLLエントリポイントとActionのためのコールバック実装を行っています。
ほぼ全てにコメントをつけているので大丈夫かもしれませんが、ポイントは以下の通り。
・Pluginがロードされるとreaper_plugin_info_t* recがエントリポイントにやってくる
 (Pluginアンロード時はまたエントリポイントが呼ばれますが、nullptrが来る)
・REAPERAPI_LoadAPI()を読んでAPIを使えるようにする
・plugin_register()でコールバックやActionなどを登録(名前の先頭にハイフン'-'を付けると登録解除)
・REAPERでActionを実行すると、hookcommand2で登録したコールバックが呼ばれる
 (他にhookcommandという方もあるのですが、これは後々とりあげる予定です)
・ActionList右上にSection指定があるのですが、これらに個別にActionを登録可能で、
 今回はSection毎に登録できる方法をとったサンプルにしています。
ActionListSections
 ↑ActionListのSection

■reaper_HelloAction(64).dll
実は筆者が最初うまくいかずにハマってしまったのはこのDLL名でした。
REAPERは "reaper_" というプレフィックスがついたDLLしかプラグインとして認識しません。
SWSも reaper_sws.dll だし、reapackも reaper_reapack.dll でした。
自分は最初TestPlugin.dll とかそういう名前にしてた気がしますが、それだとDLLのエントリポイントに
一切呼び出しが入ってきません。
恐らく余計なDLLロードやチェックで起動が重くなるのを防いでいるのではないかと推測していますが、このDLL名には注意して下さい。

DLL名の落とし穴は実はまだ別にあったりして、自分はそこでもハマりました。
が、長くなってきたのでそれについてはまた別の機会にでも。

Hello C++ REAPER Action Extension!

最近REAPERをいじりはじめたら楽しいので、共有できる情報はどんどん出していきたい。
というところからぺろりが始めてみたブログです。
飽きたらサクっとやめたりして・・・いやいや頑張ります。

一発目はREAPERのインストールとか簡単な使い方とか便利なAction紹介とか全部すっとばして
「C++でActionを実装するExtension DLLを作る」
ってとこから行ってみたいと思います(すっとばしすぎ)。

これって意外とまとまった情報が少ないようで、もちろん日本語の情報は壊滅的。
SWSのソースを頑張って読んで調べるか、公式にあるExtensionSDK(古い)を見るか
といったところが近道のようです。
(自分はしばらくSDKの存在に気づかず、SWSのソースを眺めて習得しました)
・SWS: http://www.sws-extension.org/
・GitHub (SWS): https://github.com/reaper-oss/sws
SWSはVisualStudio2013で簡単にビルドできるので、いろいろと参考になります。

細かい説明などは次回からにして、今回はとにかくシンプルなソースでExtensionを
作れるものを用意しました。
reaper_HelloAction.zip

zipを解凍して、reaper_HelloAction.slnをVisualStudio2015で開いてビルドします。
これを例えばx64でビルドすると
%APPDATA%\REAPER\UserPlugins\reaper_HelloAction64.dll
というパスにDLLがコピーされます。
あとはREAPER(64bit版)を起動してやれば起動時にこのDLLが読み込まれて、
ActionListにActionが並ぶようになります。
↓ "pelo" で検索してコマンドが無事出てきている例
HelloActionInActionList

この "Pelo: Hello World!" のActionを実行すると、REAPERのConsoleに文字列が表示されます。
HelloWorldOutput
これで世界一シンプルな(?)、C++によるActionとExtensionDLLが実装できました。

次回からはもう少し詳しい説明やらなんやらを書いていこうかと思います。

このブログについて
ぺろりがREAPERで遊びたいというだけのブログかもしれない

必ずこちらをお読みください

twitter: @pelori

管理人用
  • ライブドアブログ