首頁 > 後端開發 > C++ > 在 C# 和 C DLL 之間傳遞字串時如何避免 System.AccessViolationException?

在 C# 和 C DLL 之間傳遞字串時如何避免 System.AccessViolationException?

DDD
發布: 2025-01-02 19:01:38
原創
220 人瀏覽過

How to Avoid System.AccessViolationException When Passing Strings Between C# and a C   DLL?

在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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板