環境
OS: windows10 pro 64bit
IDE: VS2017 free
Unity :
OpenCV + aruce : ソースからビルドの後半参照
OpenCV : OpenCV Plus Unity(無料版)
Unityプラグイン
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個のターミネートで。
駄目なときは絶対パスでかく。