字段上的 PInvoke 实现
PInvoke Implementation on Fields
所以今天我在浏览 ILSpy 以更好地了解 .NET 如何对外部方法执行 DllImports,当我遇到一些奇怪的事情时:
在搜索对 System.Reflection.MethodAttributes
枚举中定义的枚举值 PInvokeImpl
的引用时,我注意到 System.Reflection.FieldAttributes
.
中的匹配定义
果然,这似乎不仅仅是在幕后重复使用枚举值:System.Reflection.FieldInfo
有一个公开定义的 属性 称为 IsPinvokeImpl
,它专门检查是否设置了此实现标志。
有趣的是,MethodInfo
class 甚至没有这个 属性 - 它必须从 MethodImplementationFlags
属性 来确定。
问题:
一个字段是否真的可以被 PInvoke 实现,或者这只是 .NET 框架中的一个存根实现,用于平衡字段装饰和方法装饰?
如果可能的话,可以用 C# 完成吗,或者这是一个需要 C++/CLI 的功能?
PinvokeImpl Reserved for future use.
所以我会说:
问:PInvoke 是否真的可以实现一个字段
答:没有
当您查看 FieldAttributes 的 MSDN 描述时,您会看到它被记录为 "Reserved for future use"。那个未来还没有到来,所以它的意图还没有确定。
FieldAttributes 等类型不是任意的,它们遵循 CLI 规范。 Ecma-335 明确了 .NET 程序集中的元数据应该是什么样子以及应该如何解释它。这份文件确实揭示了一个有趣的怪癖。
第 II.16.1 章描述了字段属性,您将看到元数据标记与 FieldAttributes 枚举之间的紧密匹配。但是请注意,pinvokeimpl
在该章中 缺失 。
第II.23.1.5章给出了属性的具体取值,其PInvokeImpl值为0x2000。说明是 "Implementation is forwarded through PInvoke"。与 II.23.1.10 相比,描述了方法属性。它有许多与字段属性相同的值。
这看起来很像 copy/paste 错误 :)
深入挖掘 .NET Framework 源代码,CLR 和抖动只考虑方法上的 pinvokeimpl。然而,C# 编译器似乎基于 CLI 规范并实际设置了属性。出现在emit.cpp、RegMeta::_DefinePinvokeMap()函数中,如果这个函数是为字段而不是方法调用的,它会设置属性。这从未真正发生过。
所以今天我在浏览 ILSpy 以更好地了解 .NET 如何对外部方法执行 DllImports,当我遇到一些奇怪的事情时:
在搜索对 System.Reflection.MethodAttributes
枚举中定义的枚举值 PInvokeImpl
的引用时,我注意到 System.Reflection.FieldAttributes
.
果然,这似乎不仅仅是在幕后重复使用枚举值:System.Reflection.FieldInfo
有一个公开定义的 属性 称为 IsPinvokeImpl
,它专门检查是否设置了此实现标志。
有趣的是,MethodInfo
class 甚至没有这个 属性 - 它必须从 MethodImplementationFlags
属性 来确定。
问题:
一个字段是否真的可以被 PInvoke 实现,或者这只是 .NET 框架中的一个存根实现,用于平衡字段装饰和方法装饰?
如果可能的话,可以用 C# 完成吗,或者这是一个需要 C++/CLI 的功能?
PinvokeImpl Reserved for future use.
所以我会说:
问:PInvoke 是否真的可以实现一个字段
答:没有
当您查看 FieldAttributes 的 MSDN 描述时,您会看到它被记录为 "Reserved for future use"。那个未来还没有到来,所以它的意图还没有确定。
FieldAttributes 等类型不是任意的,它们遵循 CLI 规范。 Ecma-335 明确了 .NET 程序集中的元数据应该是什么样子以及应该如何解释它。这份文件确实揭示了一个有趣的怪癖。
第 II.16.1 章描述了字段属性,您将看到元数据标记与 FieldAttributes 枚举之间的紧密匹配。但是请注意,pinvokeimpl
在该章中 缺失 。
第II.23.1.5章给出了属性的具体取值,其PInvokeImpl值为0x2000。说明是 "Implementation is forwarded through PInvoke"。与 II.23.1.10 相比,描述了方法属性。它有许多与字段属性相同的值。
这看起来很像 copy/paste 错误 :)
深入挖掘 .NET Framework 源代码,CLR 和抖动只考虑方法上的 pinvokeimpl。然而,C# 编译器似乎基于 CLI 规范并实际设置了属性。出现在emit.cpp、RegMeta::_DefinePinvokeMap()函数中,如果这个函数是为字段而不是方法调用的,它会设置属性。这从未真正发生过。