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

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

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

bool Foo() { return false; } 

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

 public class FooAPI { [DllImport("Foo.dll")] public static extern bool Foo(); } ... bool b = FooAPI.Foo(); if (!b) { // Throw an exception } 

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

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

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

提前致谢!

试试[return: MarshalAs (UnmanagedType.I1)] 。 默认情况下,C#interop将C# bool编组为Win32 BOOL ,它与int相同,而C ++ bool是一个字节AFAIR。 因此,C#的默认编组期望返回值为eax寄存器中的BOOL ,并且因为C ++ boolal返回,所以会获取一些非零垃圾。

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

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

 extern "C" __declspec(dllexport) bool __stdcall Foo() { return false; } 

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

 013D138E xor al,al 

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

我使用了signed int

C ++代码

  extern "C" __declspec(dllexport) signed int TestDouble(double* output) { *output = 1.3; return true; } 

C#代码

  [DllImport("abc.dll", EntryPoint = "TestDouble", CallingConvention = CallingConvention.Cdecl)] public static extern bool TestDouble(out double output);