gpt4 book ai didi

c# - 为什么 DllImport for C bool as UnmanagedType.I1 throws but as byte it works

转载 作者:太空狗 更新时间:2023-10-29 15:26:46 24 4
gpt4 key购买 nike

这是一个简单的 C 代码(VS 2013 C++ 项目,“编译为 C”):

typedef struct {
bool bool_value;
} BoolContainer;

BoolContainer create_bool_container (bool bool_value)
{
return (BoolContainer) { bool_value };
}

这是我的 P/Invoke 包装器

public partial class NativeMethods
{
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
public static extern BoolContainer create_bool_container([MarshalAs(UnmanagedType.I1)] bool bool_value);
}

以下是 BoolContainer 的托管版本:

首先是抛出 MarshalDirectiveException: Method's type signature is not PInvoke compatible.:

public struct BoolContainer // Marshal.SizeOf(typeof(BoolContainer)) = 1
{
[MarshalAs(UnmanagedType.I1)] // same with UnmanagedType.U1
public bool bool_value;
}

第二个是工作:

public struct BoolContainer // Marshal.SizeOf(typeof(BoolContainer)) = 1
{
public byte bool_value;
}

测试代码:

BoolContainer boolContainer = NativeMethods.create_bool_container(true);

对于返回结构中的任何 boolean 成员,DllImport 似乎忽略了 MarshalAs。有没有办法在托管声明中保留 bool

最佳答案

作为返回类型的结构在互操作中非常困难,它们不适合 CPU 寄存器。这是在 native 代码中由调用者在其堆栈帧上为返回值保留空间并将指针传递给被调用者来处理的。然后通过指针复制返回值。一般来说,这是一个非常麻烦的功能,不同的 C 编译器有不同的策略来传递该指针。 pinvoke 编码器采用 MSVC 行为。

这是不可blittable 的结构的问题,换句话说,当它的布局不再与 native 代码所需的非托管结构完全匹配时。这需要一个额外的步骤来将非托管结构转换为托管结构,相当于 Marshal.PtrToStructure()。例如,如果将字符串字段添加到结构中,就会看到这一点。这使得它不可 blittable,因为必须将 C 字符串转换为 System.String,您将得到完全相同的异常。

在您的案例中有类似的问题,bool 也是一种很难互操作的类型。由于 C 语言没有类型,后来添加了高度不兼容的选择。在 C++ 和 CLR 中为 1 个字节,在 COM 中为 2 个字节,在 C 和 winapi 中为 4 个字节。 pinvoke marshaller 选择 winapi 版本作为默认版本,使其匹配 BOOL,这是 pinvoke 的最常见原因。这迫使您添加 [MarshalAs] 属性,这也需要额外的工作,同样需要由等效的 Marshal.PtrToStructure() 来完成。

所以 pinvoke 编码器缺少的是对这个额外步骤的支持,即调用后返回值的自定义编码。不确定这是设计约束还是资源约束。可能两者兼而有之,non-blittable struct 成员的所有权在非托管语言中是完全未指定的,并且对其进行猜测,尤其是 作为返回值,很少有结果。因此,他们很可能已经做出决定,认为开发该功能不值得,因为成功的几率很低。这当然是猜测。

改用 byte 是一个很好的解决方法。

关于c# - 为什么 DllImport for C bool as UnmanagedType.I1 throws but as byte it works,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20035826/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com