从执行反向P/Invoke的函数返回时发生访问冲突 我有一个C托管项目,它导入一个非托管C++ DLL。我想要的是使用我在C#代码中编写的日志函数来实现日志记录。因此,我在C#侧添加了以下内容:
以下是我的记录器类定义:从执行反向P/Invoke的函数返回时发生访问冲突 我有一个C托管项目,它导入一个非托管C++ DLL。我想要的是使用我在C#代码中编写的日志函数来实现日志记录。因此,我在C#侧添加了以下内容:,c#,c++,logging,dll,pinvoke,C#,C++,Logging,Dll,Pinvoke,以下是我的记录器类定义: public static class Logger { public static void LogMessage(string msg) { Console.WriteLine(msg); fileStream.Write(msg); } } 我在C++侧头上有以下内容: #define MY_C_API extern "C" __declspec(dllexport); MY_C_API __declsp
public static class Logger
{
public static void LogMessage(string msg)
{
Console.WriteLine(msg);
fileStream.Write(msg);
}
}
我在C++侧头上有以下内容:
#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应用程序的一部分。问题在于回调的调用约定不匹配。本机代码期望回调为
cdecl
,但托管代码将其声明为stdcall
。您可以在托管代码或本机代码中修复此问题。为了简单起见,我将展示如何在托管代码中修复它
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void FunctionPointer(string msg);
其他几点:
SetLastError
参数设置为true
,因为函数没有设置Win32 last错误
。作为一般规则,您应该避免不安全的,
,并且您不需要它在上面,init被声明为void,但您返回的是true,它是否真的成功地调用了C代码?另外,我假设你上面有loggerPtr,你真的是指loggerDelegate?,对不起,放在这里的时候出错了。我想我现在把它们修好了。我把你的问题退回去了。你的编辑只是将我的代码移到了问题中,使我的答案看起来很愚蠢。谢谢你的帮助。不幸的是,我仍然有这个问题。我认为这与LPCTSTR类型或其他编组问题有关。请尝试最新更新。我在调用约定中发现了另一个不匹配。我刚刚测试了我的代码。它起作用了。我想你的接受意味着你也发现了同样的问题。读了一点关于我的文章后,我明白了为什么问题现在发生了。“在CDECL中,参数按相反顺序推送到堆栈上,调用者清除堆栈,结果通过处理器注册表返回(稍后我将其称为“寄存器A”)。在STDCALL中有一个区别,调用者不清除堆栈,被调用者清除。”是的,堆栈清理是问题所在。
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void FunctionPointer(string msg);