【发布时间】:2019-01-23 19:18:47
【问题描述】:
我觉得问这个问题很荒谬,但我有一个问题我已经研究了好几个小时了,但我终其一生都无法弄清楚哪里出了问题。
我在 C DLL 中定义了以下函数签名:
__declspec(dllexport) _Bool __cdecl cs_support(int query);
我在内部类中创建了以下 P/Invoke 签名等效项:
[DllImport("capstone", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool cs_support(int queryOption);
内部类在 .NET 项目中定义,该项目构建 2 个程序集,1 个用于 .NET Framework,一个用于 .NET Core。
我创建了一个小型 .NET 命令行应用程序,它同时加载 .NET 程序集和 C DLL,并按如下方式调用函数:
var isSupported = NativeImport.cs_support(65503);
现在这是我无法弄清楚的有趣之处。如果应用程序以 X86 为目标,我调用该函数一次,如果它以 X64 为目标(因此加载了 C DLL 的 X86 或 X64 版本),我得到不同的值!更诡异的是,X64 版本返回正确值,而 X86 版本则没有!
我可以访问 C DLL 的源代码,它没有处理器指令可以根据目标平台为同一输入返回不同的值。无论目标平台如何,C 代码实际上都非常简单,应该为相同的输入返回相同的值。
此外,当我创建一个小型 C 命令行应用程序进行测试时,无论目标平台如何,都会返回相同的正确值。
所以似乎只有当 C DLL 由 .NET 加载并 P/Invoked 时,我才会看到这种行为!
所以我的问题是,为什么会这样?是否有一些奇怪的 P/Invoke 行为会导致我必须注意这一点?
如果这很重要,我在 Windows 10 64 位上运行。
谢谢!
【问题讨论】:
-
什么是
_Bool -
DLL 中是否有任何数学运算会溢出 32 位整数?不过,我想这也会出现在命令行测试中
-
dll 可以记录调试信息,还是可以将 C 调试器附加到 .net 应用程序以查看 dll 中发生了什么?
-
你的
_Bool真的是基于bool而不是BOOL吗?请查看此处以了解编组“本机”bool和BOOL的区别:blogs.msdn.microsoft.com/jaredpar/2008/10/14/…(bool是 C++ 数据类型,而BOOL是由 Windows API 声明的不同数据类型) -
@9ee1,解释在我链接的文章中。长话短说,C 没有
bool数据类型。bool是 C++ 数据类型。由于 Windows API(Win32 API)基于 C(不是 C++),它定义了自己的BOOL数据类型,长度为 4 个字节。 .NET 编组器默认在 p/invoking 时将 C# bool 编组到/来自 Windows APIBOOL(4 个字节),除非特别指示要采取不同的方式;-)