最新の更新情報

2010年3月
« 2月   4月 »
 123456
78910111213
14151617181920
21222324252627
28293031  

本ブログのURL

qrcode.png

雨雲の動き

お天気

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

C#&アンマネージDLLマーシャリング 普通の配列の受け取り


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

関連記事



 
 

【追記】

GCHandleを利用した
C#&アンマネージDLL 普通の配列の引渡し

方法を記載しました.参考にどうぞ!



いや,アンマネージな構造体配列の受け取りは,大昔書いていたんだけど
intやら,floatやらの配列は,p/Invokeが良きに計らってくれると思ってたり

今日,とある画像解析エンジン構築中にどっぷりハマって...

画像中,しきい値を超えた,画素ブロックの
ブロック内重心座標XYを,各々floatの配列で戻そうとしたのであった

これが,動かねぇ~(涙
引っかかったのは,間違いなく,アンマネージ側DLLでセットした配列ポインタの受け取り部

でもまぁ,何のことはない,Marshal.Copy()を使えってことで(汗

後から来られる人のために,書いておきまする

C++(ソースは抜粋)
C++:
  1. //souBuf  画像バッファへのポインタ
  2. //length  画像バッファ長
  3. //X       座標配列ポインタを格納するポインタ(受け取り)
  4. //Y       座標配列ポインタを格納するポインタ(受け取り)
  5. //Count   座標配列要素数を格納するポインタ(受け取り)
  6. extern "C" int WINAPI BMCalc_GetLoc(BYTE* souBuf, int length, float* &X, float* &Y, int &Count)                 
  7. {
  8.  
  9.   ClearArrayList();                //m_PointArrayの要素の破棄
  10.   GetLocCore(souBuf, length);     //画像からブロック重心座標の抽出メソッド(割愛)
  11.  
  12.   if (m_XArray != NULL)
  13.   {
  14.     delete m_XArray;
  15.   }
  16.  
  17.   if (m_YArray != NULL)
  18.   {
  19.     delete m_YArray;
  20.   }
  21.  
  22.   //m_PointArrayは,座標管理クラスを保持するCObArrayのインスタンス
  23.   //これをC#に渡すために,普通のfloat配列に変換する作業が以下ズラズラと
  24.  
  25.   m_XYArrayCount = m_PointArray->GetCount();      //要素数を取得
  26.   m_XArray = new float[m_XYArrayCount];
  27.   m_YArray = new float[m_XYArrayCount];
  28.  
  29.   for(int i = 0; i <m_XYArrayCount; i++)
  30.   {
  31.     CBMCalcJob_Point *obj = (CBMCalcJob_Point *)m_PointArray->GetAt(i);
  32.  
  33.     m_XArray[i] = obj->X;
  34.     m_YArray[i] = obj->Y;
  35.   }
  36.  
  37.   //配列の先頭ポインタを,受け取り引数に乗せる
  38.   X = m_XArray;
  39.   Y = m_YArray;
  40.   Count = m_XYArrayCount;
  41.  
  42.   return 0;
  43. }


C#側
C#:
  1. //API定義
  2. [DllImport("BMImageCalc.dll")]
  3. private static extern int BMCalc_GetLoc(IntPtr souBuf, int length, ref IntPtr X,ref IntPtr Y,ref int Count);
  4.  
  5.  
  6. //bs    画像データ(Bitmapクラス)
  7. //l     処理後得られる座標を格納したList<>クラス
  8. public int GetLoc(Bitmap bS, List<classBMPoint> l)                 
  9. {
  10.   l.Clear();
  11.  
  12.   int ercd;
  13.  
  14.   IntPtr aryXPtr = IntPtr.Zero;
  15.   IntPtr aryYPtr = IntPtr.Zero;
  16.   int      aryCount = 0;
  17.  
  18.   //Bitmapをロックして,ポインタを抜き出し,DLLへ渡す
  19.   BitmapData bDataS = bS.LockBits(new Rectangle(0, 0, bS.Width, bS.Height), ImageLockMode.ReadWrite, bS.PixelFormat);
  20.   IntPtr Scan0S = bDataS.Scan0; //取り出されたIntPtr
  21.  
  22.   int bufLen = bDataS.Stride * bDataS.Height;
  23.  
  24.   //outじゃだめ refでないと正常に動かない
  25.   ercd = BMCalc_GetLoc(Scan0S, bufLen, ref aryXPtr, ref aryYPtr, ref aryCount);
  26.  
  27.   bS.UnlockBits(bDataS);
  28.  
  29.   //アンマネージな配列から
  30.   //マネージな配列へ一旦コピー
  31.   float[] aryX = new float[aryCount];
  32.   float[] aryY = new float[aryCount];
  33.  
  34.   Marshal.Copy(aryXPtr, aryX, 0,  aryCount);
  35.   Marshal.Copy(aryYPtr, aryY, 0,  aryCount);
  36.  
  37.   //以後,処理が扱い易いようにList<>クラスに載せ替える
  38.   for(int i = 0; i <aryCount; i++)
  39.   {
  40.     l.Add(new classBMPoint(aryX[i], aryY[i]));
  41.   }
  42.  
  43.   return ercd;
  44. }


C#側は,Intptrな引数をrefにて渡して,ポインタをもらってこないと
どうやら,正常に動かないっぽい

out float[]で良きにはからうかねぇ~と思ったけど,甘かったですわん

このソース,参考にドゾー

 
 
 
 

2 comments to C#&アンマネージDLLマーシャリング 普通の配列の受け取り

  • きん

    はじめまして。

    BadImageException の対処方法を探していて貴兄のページを参考にさせていただきました。
    ありがとうございます。

    C# C++ の連携をするのにデータ受渡しに苦労しているので、このページも参考になります(感謝)。

    この例題について質問ですが、
    受け渡すfloat配列は、C++ 側でAllocされていますが、Freeはどうすればよいでしょうか?
    Marshal.Copy(aryXPtr, aryX, 0, aryCount);
    Marshal.Copy(aryYPtr, aryY, 0, aryCount);
    のあとで、
    Marshal.FreeHGlobal(aryX);
    Marshal.FreeHGlobal(aryY);

    でよいのでしょうか?(自信が全然ないのですみません)

  • >>きん さま

    ようこそ!
    うちのサンプルが、参考になってうれしい限りです♪

    >>この例題について質問ですが、
    >>受け渡すfloat配列は、C++ 側でAllocされていますが、Freeはどうすればよいでしょうか?

    C++で確保したメモリは、C++側で開放すべきと思います
    このDLLでは、処理クラスのデストラクタで、
    メモリが確保されていたら、確保分の破棄の処理を行っています

    (m_XArray, m_YArrayはクラスのメンバ変数です)

    if (m_XArray != NULL)
    {
    delete m_XArray;
    }

    if (m_YArray != NULL)
    {
    delete m_YArray;
    }

    と同じコードをデストラクタに挿入してありますです

    また、わからないことがあったらよろしくですぅ ;-)

コメントを残す

  

  

  

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="">