在 C# 中从 C++ .DLL 加载值始终返回 true

Posted

技术标签:

【中文标题】在 C# 中从 C++ .DLL 加载值始终返回 true【英文标题】:Loading value from C++ .DLL in C# always returns true 【发布时间】:2020-12-10 15:57:32 【问题描述】:

我正在尝试学习如何制作 C++ DLL,所以我很容易错过一些超级基本的东西。

我目前正在用 C++ 创建一个 DLL,然后将其加载到用 C# 编写的测试环境中

测试环境使用 C#,因为我发现 Windows 窗体最适合构建原型 GUI。

我的 DLL (C++) 中有一个定义

#define BUILD_FOR_TESTBED

以及我为查找它是否已定义而创建的函数

//header file
extern "C" _declspec(dllexport) extern bool WasBuiltForTestbed();

//source file
bool WasBuiltForTestbed()

#ifdef BUILD_FOR_TESTBED

    return true;

#endif // BUILD_FOR_TESTBED
#ifndef BUILD_FOR_TESTBED

    return false;

#endif // BUILD_FOR_TESTBED//

然后我在测试环境(C#)中加载函数

[DllImport(LIBRARY_PATH, CharSet = CharSet.Unicode)]
public static extern bool WasBuiltForTestbed();

并在测试环境中写入控制台

Console.WriteLine("Built For Testbed: " + WasBuiltForTestbed());

无论我做什么,一旦加载到测试环境中,WasBuiltForTestbed() 就会返回 true。

问:我的问题是,我在这里缺少什么使函数始终返回 true?无论是否定义了 BUILD_FOR_TESTBED,如何让函数返回?

到目前为止我尝试过的测试:

“短路”函数并使其直接“返回”真或假。它仍然只返回 true。

bool WasBuiltForTestbed()  return false; 

清理库 (C++) 和测试环境 (C#) 构建。然后重建

在库中将函数 WasBuiltForTestbed() 的名称更改为 WasBuiltForrTestbed()。测试环境未能加载函数,所以它肯定会找到它认为是函数的东西并对其进行评估。

感谢任何帮助。

【问题讨论】:

在 c# 中,只要数字不为零,您就会得到 true。因此,由于某种原因,在 c++ 中设置的零在 c# 中不是零。当 c++ 和 c# 之间的变量大小不同时,通常会发生这种情况。所以尝试: ((int)WasBuiltForTestbed()).ToString() 看看返回了什么数字。 【参考方案1】:

.NET 使用 4 字节 bool,但 Visual C++ 使用 1 字节 bool。因此,您需要一个封送处理指令来告诉封送处理程序输入的内容只是一个字节。实际上,除了您的bool 之外,它只是封送 3 个字节的垃圾。垃圾通常不为零,这就是您的函数似乎返回 true 的原因。

将此添加到 DllImport。

[return:MarshalAs(UnmanagedType.I1)]

至于 .NET 选择将 bool 设为 4 字节的原因,可能主要原因是支持与使用 4 字节 BOOL 的 C++ Windows API 互操作,而不是 Visual C++ 的实现标准 C++,使用 1 字节 bool

(为什么要注意?好吧,标准 C++ 实际上并没有指定 bool... 的大小)

【讨论】:

以上是关于在 C# 中从 C++ .DLL 加载值始终返回 true的主要内容,如果未能解决你的问题,请参考以下文章

我们如何在 C# 中从 C++ DLL 中获取所有方法?

在 C# 中从 dll 加载特定类

cv::VideoCapture 在 C# 项目中从 DLL 使用时不会打开文件或流

C#编组来自C++ DLL的无符号字符返回值[重复]

在同一解决方案中从 c# 项目到 c++ 项目的 DllImport

用C++封装了Halcon的算法,返回值为Hobject类型,在C#中调用dll怎么用Hobject类型的返回值。