我有一个 C# 托管项目,它导入一个非托管 C++ DLL。我想要的是使用我在 C# 代码中编写的日志记录功能来进行日志记录。所以我在 C# 端添加了以下内容:
public struct API
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void FunctionPointer(string msg);
[DllImport("mydll.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
unsafe public static extern void setLoggerPointer(IntPtr fctPointer);
[DLLImport("mydll.dll", SetLastError = true)]
[return: MarshalAsAttribute(UnmanagedType.I1)] unsafe public static extern bool init();
}
public unsafe class MyInterface
{
public MyInterface()
{
API.FunctionPointer loggerDelegate;
loggerDelegate = new API.FunctionPointer(Logger.LogMessage);
IntPtr loggerPtr = Marshal.GetFunctionPointerForDelegate(loggerDelegate);
API.setLoggerPointer(loggerPtr);
if (API.init())
{
//do stuff
}
}
}
这是我的 Logger 类定义:
public static class Logger
{
public static void LogMessage(string msg)
{
Console.WriteLine(msg);
fileStream.Write(msg);
}
}
我在 C++ 端 header 上有以下内容:
#define MY_C_API extern "C" __declspec(dllexport);
MY_C_API __declspec(dllexport) void __stdcall setLoggerPointer( void *fctPointer(LPCTSTR msg) );
MY_C_API __declspec(dllexport) bool __stdcall init();
在 C++ 源代码中:
//global variable
void *(*logger)(LPCTSTR msg);
void __stdcall setLoggerPointer( void *fctPointer(LPCTSTR msg) )
{
logger = fctPointer;
}
bool __stdcall init()
{
logger("WOOO");
return true; //I'm getting the AccessViolation right here
}
我在从 mfc100.dll 中的 atlsimpstr.h Release() 函数中的 init() 函数返回时收到 System.AccessViolationException
有人知道我做错了什么吗?我看到的关于这类事情的所有问题都是如何在没有访问冲突的情况下执行反向 P/Invoke 但它对我来说工作正常,只是从其他调用返回时它被搞砸了,好像那部分内存现在被视为 C# 应用程序的一部分。
最佳答案
问题是回调的调用约定不匹配。您的 native 代码期望回调为 cdecl
,但托管代码将其声明为 stdcall
。您可以在托管代码或 native 代码中修复此问题。为简单起见,我将展示如何在托管代码中修复它。
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void FunctionPointer(string msg);
其他几点:
- 不要将
SetLastError
参数设置为true
,因为您的函数不会设置 Win32 最后一个错误。 - 不要在此代码中的任何地方使用
unsafe
。作为一般规则,您应该避免unsafe
并且您只是不需要它。
关于c# - 从执行反向 P/Invoke 的函数返回时发生访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15208003/