C# 中的 C++:C++ 函数(在 DLL 中)返回 false,但 C# 认为这是 true!

问题描述 投票:0回答:3

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

到目前为止,API 有一个函数,但目前它什么也没做:

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”:)

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

提前致谢!

c# c++ boolean pinvoke dllimport
3个回答
18
投票

尝试

[return: MarshalAs (UnmanagedType.I1)]
。默认情况下,C# 互操作 将 C#
bool
编组为 Win32
BOOL
,与
int
相同,而 C++
bool
是一个字节 AFAIR。因此,C# 的默认封送处理期望返回值是
BOOL
寄存器中的
eax
,并拾取一些非零垃圾,因为 C++
bool
al
中返回。


4
投票

您发布的代码片段无法工作。如果这是用 C++ 编译器编译的,那么函数名称将是

?Foo@@YA_NXZ
,而你的 C# 代码永远找不到它。调用约定也很重要,它不是默认的(
CallingConvention.StdCall
),除非你告诉编译器。您应该在某个地方告诉链接器导出该函数。

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

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

下一个问题是 C++ 编译器仅使用一个 byte 来存储

bool
。为您的返回语句生成的机器代码是:

013D138E  xor         al,al
然而,P/Invoke 编组器将假定它是 32 位整数并检查

eax

 寄存器的值。将函数的返回类型声明为 
int
BOOL
,或者在 C# 声明中使用 
[return: MarshalAs(UnmanagedType.U1)]
 属性。


-1
投票
我使用了

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);
    
© www.soinside.com 2019 - 2024. All rights reserved.