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#的默认编组预计的返回值是一个BOOL在eax寄存器中,并且因为C++拾取一些非零垃圾bool在返回al.
您发布的代码片段无法工作。如果这是用 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)]