簡體   English   中英

從C ++ DLL調用時,帶有參數的C#委托回調導致AccessViolation

[英]C# delegate callback with params cause AccessViolation when calling from C++ DLL

我有一個非托管的C ++ DLL和一個.NET應用程序,它們使用P / Invoke進行通信。 我需要從C ++ DLL更新.net應用程序中的字典。

我試圖通過以下方式做到這一點:

public delegate void MyDelegate(string address, string username);

[DllImport("MyDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SaveMyDelegate(MyDelegate callback);

private static SortedDictionary<string, string> dict = new SortedDictionary<string, string>();

public void save_delegate() {

    SaveMyDelegate(delegate(string address, string username) {
        if (username != "") {
            dict.Add(address, username);
        }
     });
 }

在C ++方面,我有:

typedef void (*MANAGED_CALLBACK)(string user_address, string username);

    extern "C" __declspec(dllexport) void SaveMyDelegate(MANAGED_CALLBACK callback);

    MANAGED_CALLBACK my_callback;
    void SaveMyDelegate(MANAGED_CALLBACK callback) {
        my_callback = callback;
    }

extern "C" __declspec(dllexport) VOID start_collection();
VOID start_collection() {
    my_callback("test", "User");
}

在C#上,我執行以下調用:

[DllImport("MyDLL.dll")]
public static extern void start_collection();

private void Button1_Click(object sender, EventArgs e) {
    save_delegate();

    start_collection();
}

當我調用start_collection ()時,出現AccessViolation異常。 我試圖通過以下方式聲明委托:

public delegate void MyDelegate(
[MarshalAs(UnmanagedType.LPStr)]string address, 
[MarshalAs(UnmanagedType.LPStr)]string username);

我還添加了以下語句:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void MyDelegate(...)

我沒有查看您代碼的每個細節,但立即發現了一些常見的p / invoke問題:

  1. 您不能將C ++字符串用作互操作類型。 您應該在C ++端使用以null結尾的字符數組。 使用std::stringc_str()方法獲取它們。
  2. 委托人可能有錯誤的調用約定。 非托管代碼(可能)使用cdecl ,因此在C#中聲明委托類型時,需要使用[UnmanagedFunctionPointer(CallingConvention.Cdecl)]屬性。
  3. 因為沒有托管引用,所以您的C#委托很容易盡早被收集(而您的非托管代碼仍保留對其的引用)。 通常,這可以通過在C#代碼的靜態變量中保留對委托的引用來解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM