使用参数的 C# 委托回调会导致从 DLL 调用时C++访问冲突
C# delegate callback with params cause AccessViolation when calling from C++ DLL
我有一个非托管C++DLL和一个使用P/Invoke进行通信的.net应用程序。我需要从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(( 时,我收到访问违规异常。我尝试通过以下方式声明委托:
public delegate void MyDelegate(
[MarshalAs(UnmanagedType.LPStr)]string address,
[MarshalAs(UnmanagedType.LPStr)]string username);
我还添加了以下声明:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void MyDelegate(...)
我没有查看您代码的每个细节,但一些常见的 p/incall 问题会立即出现:
- 不能将C++字符串用作互操作类型。您应该在C++端使用以空结尾的字符数组。使用
c_str()
方法获取这些std::string
. - 委托可能具有错误的调用约定。非托管代码(可能(使用
cdecl
,因此在 C# 中声明委托类型时需要使用[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
属性。 - 您的 C# 委托很容易被提前收集(而您的非托管代码仍包含对它的引用(,因为没有对它的托管引用。通常,可以通过在 C# 代码中的静态变量中保留对委托的引用来解决此问题。
相关文章:
- 如何安全地从 DLL 调用返回对象
- C++结构到德尔福记录dll调用
- 从 C#-DLL 调用函数的 C++ 失败
- 可视C++:XGBoost 从 DLL 调用时不起作用
- Unity3D的OpenCV dll调用导致FPS下降
- 创建一个C++DLL以从C#DLL调用方法
- 从 dll 调用 opencv 垫到 Windows 表单,图像出现故障
- 努力使用 C# 从本机 DLL 调用该方法
- WinAPI - GetLastError 在通过 COM ATL DLL 调用时始终返回 0
- 必须使用C DLL调用C#.NET方法
- 如何直接从 pdfium.dll 调用 v8 函数
- 为什么从 DLL 调用类方法需要虚拟说明符?
- VBA 中的多个 DLL 调用
- 挂钩VirtualAlloc在系统DLL调用时返回NULLPTR
- 无法从 C DLL 调用该函数
- DLL 调用涉及 strncpy() 的方法
- JNA从DLL调用C++对象-java.lang.IollegalArgumentException:Structure
- 德尔福动态DLL调用中的奇怪行为
- 从非托管 DLL 调用 UWP api
- boost::从 DLL 调用时日志格式不起作用