来自C#的C++:C++函数(在DLL中)返回false,但C#认为它是真的!

11 c# c++ dll boolean dllimport

我正在编写一个C#app,它在C++ API中调用了一些函数.我将C++代码构建到DLL中,C#代码使用DllImport调用API.(我使用.DEF文件作为C++ DLL,因此我不需要extern"C".)

到目前为止,API有一个功能,目前绝对没有任何功能:

bool Foo()
{
  return false;
}
Run Code Online (Sandbox Code Playgroud)

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

public class FooAPI
{
    [DllImport("Foo.dll")]
    public static extern bool Foo();
}

...

bool b = FooAPI.Foo(); 
if (!b) 
{ 
    // Throw an exception 
} 
Run Code Online (Sandbox Code Playgroud)

我的问题是,由于某种原因,b总是评估为TRUE.我在if(!b)上有一个断点,调试器将其报告为'true',与C++函数返回的内容无关.

C#bool和C++ bool一样吗?虽然事实并非如此,但我仍然不知道如何找到返回值为'true':)

任何人都可以帮我解决这个奇怪的差异吗?

提前致谢!

Ant*_*hyy 16

试试[return: MarshalAs (UnmanagedType.I1)].默认情况下,C#interop将C#编组bool为Win32BOOL,与intC++ 相同,而C++ bool是一个字节AFAIR.因此,C#的默认编组预计的返回值是一个BOOLeax寄存器中,并且因为C++拾取一些非零垃圾bool在返回al.


Han*_*ant 5

您发布的代码片段无法工作。如果这是用 C++ 编译器编译的,则函数名称将为?Foo@@YA_NXZ,而您的 C# 代码永远找不到它。CallingConvention.StdCall调用约定也很重要,除非您告诉编译器,否则它不是默认值 ( )。您应该在某个地方告诉链接器导出该函数。

首先声明导出的函数,使其与默认的 P/Invoke 属性兼容:

extern "C" __declspec(dllexport) 
bool __stdcall Foo() {
    return false;
}
Run Code Online (Sandbox Code Playgroud)

下一个问题是 C++ 编译器仅使用一个字节来存储bool. 为您的 return 语句生成的机器代码是:

013D138E  xor         al,al
Run Code Online (Sandbox Code Playgroud)

然而,P/Invoke 编组器将假定它是一个 32 位整数并检查寄存器的值eax。将函数的返回类型声明为intor或在 C# 声明中BOOL使用属性。[return: MarshalAs(UnmanagedType.U1)]