また,C#内のfloat配列をドカンと
アンマネージDLLに渡す必要が出てきて
もちろん,C#内のすべてのオブジェクトは,マネージ管理
ガーベジコレクションが勝手気ままに,オブジェクトのアドレスを,変えてくれまする
これじゃぁ~,アンマネージDLL側は安心して,データの受取ができない...
ってことで,まず思いついたのが
Marshal.AllocCoTaskMem()を使用して,固定アドレスなバッファを作成して,こいつに配列の中身を全コピーの上で
アンマネージDLLを呼び出しちゃえ!ってやつ
ソースはこちら
C#:
- [DllImport("hogehoge.dll")]
- private static extern int dll_TestFunc(int frameno, IntPtr ary, int aryCount);
- public int TestFunc(int frameno, ref float[] ary)
- {
- int len = ary.Length;
- Marshal.Copy(ary, 0, p, len);
- int re = dll_TestFunc(frameno, p, len);
- Marshal.FreeCoTaskMem(p);
- return re;
- }
でも,これだと,メモリリソース倍必要だし
コピーのオーバーヘッドも,ちと嫌な感じだし?
配列から直接IntPtr(しかも,マネージメモリ管理から外れるように,fixedしてくれないとまずい)
取り出せないのかねぇ~?
だったんですが,
GCHandle構造体
を使えば良いそうな.
ハンドルを取得するときに,ピン止め(GCHandleType.Pinned)するのがミソ
これで,マネージメモリ管理から外れまする
ソースはこちら
C#:
- [DllImport("hogehoge.dll")]
- private static extern int dll_TestFunc(int frameno, IntPtr ary, int aryCount);
- public int TestFunc(int frameno, ref float[] ary)
- {
- int len = ary.Length;
- GCHandle gcH = GCHandle.Alloc(ary, GCHandleType.Pinned);
- int re = dll_TestFunc(frameno, gcH.AddrOfPinnedObject(), len);
- gcH.Free();
- return re;
- }
これで,だいぶすっきりしましたわん



