来自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 ++ bool
在al
返回,所以会获取一些非零垃圾。
您发布的代码段不起作用。 如果这是用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);