C#調用C++動態庫方法及動態庫封裝總結


  我只是粗淺的學習過一些C++語法, 變量類型等基礎內容, 如有不對的地方還望指出. 如果你跟我一樣, 對指針操作不了解, 對封裝C++動態庫頭疼的話, 下面內容還是有幫助的.
   轉載請注明出處: http://www.cnblogs.com/zaiyuzhong/p/Csharp-package-Cplusplus-dll.html

  首先給一個類型轉換的表, 這個表可能跟使用時具體情況有關, 僅供參考, 點擊這里查看.

  1. C++變量類型大小寫問題:
  一種是小寫的, 比如char. 這種是系統定義的(關鍵字); 另一種是CHAR, 這個是自定義的, 有說這個是宏, 有說這個在VC++里是.Net定義的, 具體怎樣我還沒遇到過, 沒有例子供研究. C++是大小寫敏感的.

  2. int的長度問題:
  int的長度和編譯器是有關系的. 如果動態庫和封裝代碼由同一個編譯器編譯運行時, 可以不考慮轉換int長度.
  
  3. 結構體成員的長度問題:
不好描述, 舉個例子:
  C++代碼:
  typedef struct Result
  {
    char color[8];
  }
  對應C#代碼:
  public struct Result
  {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] color;
  }
  //C#中public修飾符可根據需要修改為其他訪問修飾符.
在調用前可先對數據長度進行驗證后再調用.
  
  4. 指針問題:
  有兩種情況, 一種是封裝C++函數時, 參數有指針類型的, 如果該參數是引用類型, 那么在C#中使用該參數時傳遞的也是變量指針(引用), 所以不用處理; 如果該參數是結構類型, 如int* , 封裝時需要表示為ref, 例如:
C++: int InitSDK(Config* pConfig); //Config是結構體;
C# : public int InitSDK(ref Config pConfig); //int類型是否修改參見上述問題2;

  另外一種情況比較麻煩, C++函數需要給他分配一塊內存空間:
C++: int RecogImage(const unsigned char* pbyBits, Result* pResult);
   // pbyBits[in] 指向內存圖像數據的指針,數據格式為輸入圖像的格式;
   // pResult[out] 識別結果數組, 調用方開辟pResult[nResultNum]內存;(注: 這兩行注釋是文檔上的函數說明)
Result是動態庫定義的結構體, nResultNum是自己定義的變量, 數值與這里無關, 測試后發現聲明參數類型為數組是不行的.
C#: [DllImport("dll路徑")]
  public static extern int RecogImage(IntPtr pbyBits, IntPtr pResult);
  // 這里的IntPtr雖然也是結構體, 但由於它本身就代表一個指針所以不用ref;

這個方法的調用方法如下, 開辟內存和讀取識別結果麻煩點:
 1 using System.Drawing;
 2 using System.Drawing.Imaging;
 3 
 4 //開辟識別結果數組內存
 5 int nResultNum = 6; // 數值與代碼無關
 6 var result = new Result();
 7 var rSize = Marshal.SizeOf(result);
 8 var resultsPtr = Marshal.AllocHGlobal(rSize * nResultNum);
 9 
10 //獲取圖像數據指針
11 var image = new Bitmap("路徑");
12 var bmpData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
13 
14 //識別圖像
15 var r = PlateSDK.RecogImage(bmpData.Scan0, resultsPtr);
16 
17 //讀取識別結果
18 if(r != 0) return; // 識別失敗, r為錯誤編號;
19 else
20 {
21   var results = new Result[nResultNum];
22   for(int i = 0; i < nResultNum; i++)
23     results[i] = (Result)Marshal.PtrToStructure(results + rSize * i, typeof(Result));
24 } // results 就是識別結果數組
 
        

 嗯, 其中3/4是我遇到比較麻煩的, 需要熟悉 Marshal(msdn), IntPtr(msdn) 和 MarshalAs(msdn).


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM