【问题标题】:P/Invoke: C# P/Invoking a C Function Returns Different Values Depending on Platform (X86 vs. X64)?P/Invoke:C# P/Invoking C 函数根据平台返回不同的值(X86 与 X64)?
【发布时间】: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吗?请查看此处以了解编组“本机”boolBOOL 的区别: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 API BOOL(4 个字节),除非特别指示要采取不同的方式;-)

标签: c# .net .net-core pinvoke


【解决方案1】:

根据 cmets 中的讨论,很明显问题是由返回 _Bool 值的本机函数引起的,而类型 _Bool 的字节大小为 1。

但是,默认情况下,.NET 编组器将 C# bool 编组到和来自 Windows API 数据类型 BOOL,其字节大小为 4(也是 see here)。

要正确编组单字节 _Bool 值,需要明确指示编组器将 C# bool 值编组为单字节:

[DllImport("capstone", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
internal static extern bool cs_support(int queryOption);

【讨论】:

    猜你喜欢
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多