带有C++布尔函数的C#DllImport无法正确返回

Sha*_*mah 29 c# c++ import dll invoke

我在C++ DLL中有以下功能

extern "C" __declspec(dllexport) bool Exist(const char* name)
{
 //if (g_Queues.find(name) != g_Queues.end())
 // return true;
 //else
 // return false;
 return false;
}
Run Code Online (Sandbox Code Playgroud)

在我的C#类中,我有以下内容:

[DllImport("Whisper.dll", EntryPoint="Exist", CallingConvention=CallingConvention.Cdecl)]
        public static extern bool Exist(string name);
Run Code Online (Sandbox Code Playgroud)

然而,每当我调用我的函数时,它总是返回true,即使我注释掉了我的小函数并使其返回false.我觉得我的调用约定或P/Invoking我的DLL的任何其他问题都有问题,可能与字符串和const char*相对应,但是现在我完全无能为力.我究竟做错了什么?为什么它返回true而不是false?

编辑:我已经发现这与const char*或字符串无关,因为问题仍然存在于空函数中.我试过改变Cdecl和StdCall之间的调用约定,但都没有正常工作.我还设法调试我的DLL并且它被正确调用并且确实返回false,但是一旦回到C#,它就会变成现实.更改CharSet也没有任何效果.我已经确保每次都为我的C#程序提供最新版本的DLL,所以这不应该是一个问题.再一次,当我实际上返回false时,我完全不清楚为什么结果是真的.

EDIT2: SOReader为我提供了一个修复另一个重要问题的建议,请参阅我的评论.可悲的是,它并没有解决退货问题.

EDIT3:我得出结论,将Exist(bool)的返回类型更改为(int)突然使其返回正确的数字(true = 1,false = 0).这意味着C++的bool和C#的bool之间可能存在问题.我可以继续使用int作为bool,但这仍然无法解释原始问题.也许其他人可以在这个上启发我?也许这与我使用x64这一事实有关(虽然两个poject都编译为x86)

SOR*_*der 53

我找到了解决问题的方法.您的声明应该在此编组之前: [return:MarshalAs(UnmanagedType.I1)]

所以一切都应该是这样的:

[DllImport("Whisper.dll", EntryPoint="Exist", CallingConvention=CallingConvention.Cdecl)]  
[return:MarshalAs(UnmanagedType.I1)]  
public static extern bool Exist([MarshalAs(UnmanagedType.LPStr)] string name);
Run Code Online (Sandbox Code Playgroud)

我在一个非常简单的例子中测试了它并且它工作了!

编辑
为什么会这样?C将bool定义为4字节int(正如你们所说的那样),C++将其定义为1字节.C#团队决定在PInvoke期间使用4字节bool作为默认值,因为大多数系统API函数使用4字节值作为bool.如果要更改此行为,则必须使用编组指定要使用1个字节值.


Pup*_*ppy 6

C bool实际上是int因为原始C语言中没有布尔类型.这意味着如果C#的DLLImport被设计为与C代码互操作,那么他们将期望C#bool对应于C代码int.虽然这仍然无法解释为什么错误会成为现实,但修复它应该可以解决问题.

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedtype.aspx

这表示UnmanagedType.Bool是Win32 BOOL,它是一个int.