在C# 和C DLL 之間傳遞字符串:一個最小示例
問題陳述
儘管按照看似簡單的方法,透過互通在C# 和C DLL之間傳遞字串會導致System.AccessViolationException。兩種語言的程式碼看起來都是正確的,導致人們對問題的根本原因感到困惑。
C 程式碼
C 程式碼定義了一個函數 concat,用於連接兩個字串並傳回結果。此函數使用 __declspec(dllexport) 標記為匯出到 DLL。
extern "C" { string concat(string a, string b){ return a + b; } }
C# 程式碼
在 C# 中,程式碼使用 DllImport 匯入 concat 函數。 CallingConvention 設定為 Cdecl 以符合 C 約定。
[DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)] static extern string concat(string a, string b);
異常與分析
C# 中呼叫 concat("a", "b") 會拋出異常System.AccessViolationException。此異常表示本機程式碼中發生了無效的記憶體存取。
解決方案:互通相容型別
問題的罪魁禍首在於使用 C std ::跨越互通邊界的字串。 C# 無法直接建立或處理 std::string 物件。相反,必須採用互通相容的類型來進行資料交換。
互通友善的資料型別
適當的互通型別包括用於傳遞字串的空終止字元陣列C# 到C .將字串從C 傳遞到C# 時,可以使用StringBuilder,呼叫者分配緩衝區,被呼叫者寫入緩衝區。
修改程式碼
在 C 中, concat 函數可以使用 char* 和 int 參數聲明,以接收緩衝區及其長度。
extern "C" { void concat(char *str, int len) { // Concatenate strings and write to buffer } }
中C# 可以利用 StringBuilder。
[DllImport("...", CallingConvention = CallingConvention.Cdecl)] static extern void concat(StringBuilder str, int len); .... StringBuilder sb = new StringBuilder(10); concat(sb, sb.Capacity);
透過使用互通相容的字串類型,可以有效地促進 C# 和 C DLL 之間的字串交換。
以上是在 C# 和 C DLL 之間傳遞字串時如何避免 System.AccessViolationException?的詳細內容。更多資訊請關注PHP中文網其他相關文章!