Unityプラグイン/C++


環境

OS: windows10 pro 64bit
IDE: VS2017 free
Unity :
OpenCV + aruce : ソースからビルドの後半参照
OpenCV : OpenCV Plus Unity(無料版)

Unityプラグイン

gitignore

プラグインのひな型

Unityプロジェクト設定

a. Asset直下にPluginsフォルダを作成する。「\Assets\Plugins\x86_64」
b. 呼び出しテスト

extern "C"
{
    int EXPORT_API PrintNumber() {
        return 999;
    }
}

int main_dll(int id)
{
    const char* lpBuffer = "hogehoge.dll";
    HMODULE hModule = LoadLibrary((LPCSTR)lpBuffer);
    if (hModule == NULL) {
        assert(0);
        return 0;
    }
    g_hModule = hModule;//HMODULE

    FUNC lpFunc = (FUNC)GetProcAddress(hModule, "PrintNumber");
    return lpFunc();
}

C#

using System.Runtime.InteropServices;

    [DllImport("plugin")]
    private static extern int PrintNumber();

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log(PrintNumber());   
    }

<結果>

プラグインをx64ビルドしたらUnityもx64にしてください。

unsafe/mcs.rsp

メモリコピー高速化等でunsafeは有効にした方がよいです。
smcs.rspは名称変更

インターフェース

C++とC#のインターフェースは色々あります。

マーシャルコピー

Marshal.Copy メソッド

データ受け渡し(プラグイン -> C#)

プラグインC++の方
EXPORT_API void* GetColorBuffer(int* len)

これをC#から呼んでデータを保持する。メモリコピーが発生する。C++とC#のメモリ管理の違いから必要になる。高速化もできるけど面倒。

{
    int len = 0;
    IntPtr colBuff = GetColorBuffer(ref len);
    byte[] dst = new byte[len];

    Marshal.Copy(colBuff, dst, 0, len); // CV_8UC4

    _Texture.LoadRawTextureData(dst);
    _Texture.Apply();

    if (m_image != null)
        m_image.material.mainTexture = _Texture;
}

データ受け渡し(プラグイン <= C#)


int len = 10;
IntPtr data = Marshal.AllocHGlobal(len*1 );

byte[] src= new byte[len];
for( int i = 0; i< 10; i++){
src[i] = (byte)(i+30);
}
Marshal.Copy(src,0, data, len);//src ,dst
int result = SetColorBuffer(ref len, data);
Debug.Log(string.Format("{0}\n",result));


    //private static extern int SetColorBuffer( ref int len, IntPtr data );
    EXPORT_API int SetColorBuffer( int* len, void* _data )
    {
        int tlen = *len;
        BYTE* data = (BYTE*)_data;
        int sum = 0;
        for( int i = 0;i < tlen; i++){
            printf( "%x", data[i] );
            sum += data[i];
        }

        return sum+1;
    }

ビルド後イベント

pluginはVSでビルドあとに自動でUnity-Assets-Pluginsにコピーするとよいです。
Unityは再起動が必要です。ホットリロードの方法もあるけど不安定になった。
パス指定は¥マーク2個のターミネートで。
駄目なときは絶対パスでかく。

デバッグ

参考