最新の更新情報

 
このブログ「吟遊詩人の戯言」 の記事検索...

C#&アンマネージDLL 普通の配列の引渡し

関連記事

また,C#内のfloat配列をドカンと
アンマネージDLLに渡す必要が出てきて

もちろん,C#内のすべてのオブジェクトは,マネージ管理
ガーベジコレクションが勝手気ままに,オブジェクトのアドレスを,変えてくれまする

これじゃぁ~,アンマネージDLL側は安心して,データの受取ができない...

ってことで,まず思いついたのが
Marshal.AllocCoTaskMem()を使用して,固定アドレスなバッファを作成して,こいつに配列の中身を全コピーの上で
アンマネージDLLを呼び出しちゃえ!ってやつ

ソースはこちら

[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;

    IntPtr p = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(float)) * len);

    Marshal.Copy(ary,      0, p, len);

    int re = dll_TestFunc(frameno, p, len);

    Marshal.FreeCoTaskMem(p);

    return re;
}

でも,これだと,メモリリソース倍必要だし
コピーのオーバーヘッドも,ちと嫌な感じだし?

配列から直接IntPtr(しかも,マネージメモリ管理から外れるように,fixedしてくれないとまずい)
取り出せないのかねぇ~?

だったんですが,

GCHandle構造体

を使えば良いそうな.

ハンドルを取得するときに,ピン止め(GCHandleType.Pinned)するのがミソ
これで,マネージメモリ管理から外れまする

ソースはこちら
[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;
}

これで,だいぶすっきりしましたわん 😉

 
 
 
 

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <img localsrc="" alt="">