概要
ネイティブで書かれたプラグインを、使うことはあっても自分で書いたことがなかったのでHello Worldしてみたメモです。
ちなみに、できるだけ動作を把握する意味も込めてコマンドラインで作ることを前提としています。
開発環境を整える
最初、Git Bashを使っていたのでそこにgcc
コマンドが入っていてそれを利用していたのですが、ごく簡単な関数を書いてインポートしたところエラーが。
(と思ったら、会社のPCでの環境だった。いつgcc入れたっけな・・。デフォルトでは入ってませんでした)
$ Failed to load 'Assets/Plugins/************.dll', expected 64 bit architecture
64bitを期待してるけど、32bit向けに作られたものですよ、ということ。
ならばと、64bit向けにコンパイルすればいいのね、はいはい、と思いつつ、-m64
オプションを付けて実行するも・・・
$ sorry, unimplemented: 64-bit mode not compiled in
MINGW64って書いてあるのに、なんでさ。
その後、色々調べてみたら、MINGW64自体を使うこと自体は間違っていない模様。
64bit版で書き出せるコマンドがあるらしく探してみるものの、どうもGit Bashはビルドが違うのか、該当のコマンドが見当たりませんでした。
なので、別途新しくMINGW64をインストール。
このへん(Windowsの無料で使える 64bit/32bit C/C++コンパイラ)を参考にしました。
x86_64
向けにコンパイルするには、以下の位置にあるコマンドを利用します。
path/to/location/mingw-w64/x86_64-7.2.0-win32-seh-rt_v5-rev1/mingw64/bin/x86_64-w64-mingw32-gcc
コンパイルする
これに、-m64
オプションを付けてコンパイルしたところ、無事に64bit向けにコンパイルすることができました。
$ x86_64-w64-mingw32-gcc -m64 -c anyplugin.c
そして、生成されたオブジェクトファイル(.o
)を、DLLに変換します。
$ x86_64-w64-mingw32-gcc -shared -o anyplugin.dll anyplugin.o
これで無事にDLLファイルが作成されます。
※ Pathを通して↑のコマンドを使ってます。
コンパイルされたファイルのアーキテクチャを確認する
ちなみに、すでにコンパイルされているdllやオブジェクトファイルがどのアーキテクチャ向けにビルドされているかを確認するには、Visual Studioに同梱されているdumpbin.exe
を利用すると分かるようです。
該当のexeは以下の場所らへんにあります。(インストール環境による)
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin
このあたりの詳細は以下を参照ください。
そして、チェックしたいファイルを引数に以下のように実行します。
$ dumpbin /headers anyplugin.o
すると、ダーっと色々な情報が表示されますが、先頭のほうにある、
// ... 略 ... FILE HEADER VALUES 8664 machine (x64) // ... 略 ...
を見てみると、x64
と書かれているので、64bit向けにコンパイルできていることが確認できます。
Cで書いたDLLを読み込んでUnityで実行する
さて、これでDLLを作成する準備が整いました。
最後に、ごく簡単なサンプルを書いて終わりにしたいと思います。
Cで処理を書く
今回はサンプルなので、Cで簡単な処理を書いてみます。
// plugin.c int Add(int a, int b) { return a + b; }
さて、これをUnityのC#側で利用できるようにします。
前述のようにコンパイルを行い、DLLファイルを作成します。
そしてそれを、Assets/Plugins
フォルダにコピーし、以下のようにC#側で呼び出します。
// ... 略 ... using System.Runtime.InteropServices; // <- DllImportを使うために追加 public class AnyClass : MonoBehaviour { private void Start() { int test = Add(1, 2); Debug.Log(test); // -> 3 } // プラグインのファイル名を指定する [DllImport("plugin") private static extern int Add(int a, int b); }
橋渡しができたら、あとは実際の処理を書いていくことでネイティブ側のコードを実行することができるようになります。
参考
なお、共有ライブラリのコンパイル周りについては、過去にQiita記事に書いているので、よかったら見てみてください。