e.blog

主にUnity/UE周りのことについてまとめていきます

UnityのネイティブプラグインをC/C++で作成する準備

概要

ネイティブで書かれたプラグインを、使うことはあっても自分で書いたことがなかったので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

このあたりの詳細は以下を参照ください。

rms-099.hatenablog.jp

d.hatena.ne.jp

そして、チェックしたいファイルを引数に以下のように実行します。

$ 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記事に書いているので、よかったら見てみてください。

qiita.com