gpt4 book ai didi

c# - C# 是否强制 `unmanaged` 类型为 "blittable"?

转载 作者:行者123 更新时间:2023-12-05 06:06:13 32 4
gpt4 key购买 nike

我想知道 C# 7.3's Unmanaged type constraint提供语言支持以强制类型可 blittable。根据Blittable and Non-Blittable types正确地进行平台调用需要断言返回类型是 blittable:

Structures that are returned from platform invoke calls must be blittable types. Platform invoke does not support non-blittable structures as return types.

然而,官方文档似乎没有在任何地方说明 C# 强制 unmanaged 类型是“blittable”。我很担心这样假设,因为有证据表明,至少在某个时候,一个类型是否“可复制”只能凭经验确定。

非托管类型约束文档

The C# 7.3 "Unmanaged type constraint" proposal包括以下内容:

The unmanaged constraint feature will give language enforcement to the class of types known as "unmanaged types" in the C# language spec. ...

...

Blittable vs. Unmanaged

The F# language has a very similar feature which uses the keyword unmanaged. The blittable name comes from the use in Midori. May want to look to precedence here and use unmanaged instead.

Resolution The language decide to use unmanaged

...

此处的短语“非托管类型”似乎指的是 Unsafe code - Pointer Types of the draft C# 6 specification 中定义的“unmanaged_type” (我没有在 the C# 5 ECMA standard 中找到类似的引用资料)。 unmanaged_type 定义如下:

An unmanaged_type is any type that isn't a reference_type or constructed type, and doesn't contain reference_type or constructed type fields at any level of nesting. In other words, an unmanaged_type is one of the following:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
  • Any enum_type.
  • Any pointer_type.
  • Any user-defined struct_type that is not a constructed type and contains fields of unmanaged_types only.

我没有找到 interop marshaling documentation 中提到的 C# 7.3 的 unmanaged 类型约束;该文档似乎早于该功能。

Blittable 类型文档

Blittable and Non-blittable Types指出以下内容是可复制的:

  • System.Byte, System.SByte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.UInt64, System.IntPtr >、System.UIntPtrSystem.SingleSystem.Double
  • blittable 类型的一维数组,例如整数数组。但是,包含可 blittable 类型的变量数组的类型本身不可 blittable。
  • 格式化值类型只包含 blittable 类型(和类,如果它们被编码为格式化类型)。有关格式化值类型的详细信息,请参阅值类型的默认编码(marshal)处理。

是否每个非托管类型都是“Blittable”?

起初我认为上面的定义意味着每个 unmanaged 类型都是“blittable”。但是我还没有找到任何官方文件来说明这一点。我找到的最接近的是 this reply从(据我了解时间线)在 unmanaged 类型约束功能实现之前:

How is this related to Blittable Types in Interop Marshaling? The same? or similar but bit different?

都是一样的

这似乎是肯定的证据,但它也是作为设计决策基础的相当薄弱的证据。 (FWIW,这种交换也可以解释为所有“blittable”类型都是 unmanaged 的意思,这似乎不太可能是真的。)

根据文档,bool 不是“blittable”,System.Booleanunmanaged。那个并发症is acknowledged but not directly addressed for the interop marshaler in the original proposal.

为什么我对此感到担忧

我不是一名活跃的 C# 开发人员,而这方面的历史似乎已经展开,并且肯定有我错过的线索。在我发现的线索中,很多都是负面的;似乎曾经有一段时间,P/Invoke 的实现抵制了区分 blittable 和 non-blittable 类型的总内涵定义。换句话说,至少在某些 C# 版本中,先验 确认互操作编码(marshal)拆收器是否认为某个类型是可 blittable 是非常重要的(或者可能是不可能的)。或者至少看起来是这样。例如,Hans Passant wrote in 2015

There is no easy way to find out if a type is blittable, other than it not working correctly or by using the debugger and compare pointer values.

另一个线索是 The fastest way to check if a type is blittable? 中的每个答案的方法(2012 年提出)似乎是经验性的。这似乎是进一步的负面证据。

我想可能所有 unmanaged 类型都是“blittable”但并非所有“blittable”类型都是 unmanaged。但这只是我的猜测。

最佳答案

Hans Passant confirmed the answer in the negative.

No, simplest counter-example is a struct with a bool field. Never blittable, okay to meet the constraint...

这似乎是得出答案是否定结论的充分依据。

我认为 Hans 回答的第二部分更有趣:

It just doesn't make sense to mix the concepts...

这与我对其他似乎暗示 unmanaged 和“blittable”是“相同”的观点的解释相反。我没有找到任何关于 Hans 认为混合 unmanaged 和“blittable”概念没有意义的观点的详细说明。但我已经形成了自己的观点。

“blittable”的定义

术语“blittable”对于不同的人和不同的上下文似乎意味着略有不同的东西(example 12)。我将使用 here 中的以下定义对于此答案的其余部分:

Blittable types are types that have the same bit-level representation in managed and native code. As such they do not need to be converted to another format to be marshaled to and from native code...

类型是否可“blittable”取决于对应代码的细节。

根据上述定义,一个类型是否可“blittable”取决于与您交换数据的对应代码是否以与您的代码相同的方式解释类型的位。 boolBOOL 提供了一个很好的例子:

  • CLI specification包含“ bool 数据类型”的按位定义,如下所示:
    • 占用内存1个字节
    • 具有任何一个或多个位集的位模式表示为真
    • 全零的位模式表示值为 false
  • Win32 APIBOOL 定义为 intMSVC's int是 32 位宽。
  • .Net/.Net - 由于 CLI 对 bool 数据类型的按位定义,将 bool 的位从 .Net 写入文件,例如,读取这些相同的位bool 不需要转换;任何 .Net 程序都将以相同的方式解释此类 bool 值的位。
  • .Net/win32 - 由于 .Net bool 和 win32 的 BOOL 按位表示之间的大小差异,在这些域之间交换 bool 值需要转换。如果不进行转换,发出 BOOL 的 win32 API 只能设置最重要的 24 位中的位来传达 true,而 .Net 可能会将其解释为 bool false。

总结

从 C# 的角度来看,一个类型是否可 blittable 取决于对应代码是否碰巧以相同的方式解释表示该类型的位。这将因交易对手而异。在 .Net 与 .Net 对手方交换数据的情况下,unmanaged 提供了一个约束,保证表示类型的位将被双方正确解释。

对于 .Net 以外的交易对手,目前不存在此类类似的语言限制。而且我不希望 C# 中存在这样的约束;交易对手很多,他们对表示其类型的位的解释肯定是以 C# 规范无法依赖的方式定义的。

关于c# - C# 是否强制 `unmanaged` 类型为 "blittable"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65833341/

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