我只是粗淺的學習過一些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).