最新の更新情報

2012年2月
« 1月    
 1234
567891011
12131415161718
19202122232425
26272829  

本ブログのURL

qrcode.png

雨雲の動き

お天気

 
 
吟遊詩人の戯言 内専用の記事検索...
 
 

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


キーワード(クリックで関連記事が読めます) →

関連記事



 
 

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

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

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

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

ソースはこちら

C#:
  1. [DllImport("hogehoge.dll")]
  2. private static extern int dll_TestFunc(int frameno, IntPtr ary, int aryCount);
  3.  
  4.  
  5. public int TestFunc(int frameno, ref float[] ary)
  6. {
  7.     int len = ary.Length;
  8.  
  9.     IntPtr p = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(float)) * len);
  10.  
  11.     Marshal.Copy(ary,      0, p, len);
  12.  
  13.     int re = dll_TestFunc(frameno, p, len);
  14.  
  15.     Marshal.FreeCoTaskMem(p);
  16.  
  17.     return re;
  18. }


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

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

だったんですが,

GCHandle構造体

を使えば良いそうな.

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

ソースはこちら
C#:
  1. [DllImport("hogehoge.dll")]
  2. private static extern int dll_TestFunc(int frameno, IntPtr ary, int aryCount);
  3.  
  4. public int TestFunc(int frameno, ref float[] ary)
  5. {
  6.     int len = ary.Length;
  7.  
  8.     GCHandle gcH = GCHandle.Alloc(ary, GCHandleType.Pinned);
  9.  
  10.     int re = dll_TestFunc(frameno,    gcH.AddrOfPinnedObject(), len);
  11.  
  12.     gcH.Free();
  13.  
  14.     return re;
  15. }


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

 
 
 
 

コメントを残す

  

  

  

You can use these HTML tags

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