PInvoke实现字段上

6
所以今天我在浏览ILSpy时,想更好地了解.NET如何执行外部方法的DllImports,当我遇到一些奇怪的东西时:
当搜索枚举值PInvokeImpl的引用时,该枚举值定义在System.Reflection.MethodAttributes枚举中,我注意到在System.Reflection.FieldAttributes中有一个匹配的定义。
好吧,这似乎不仅仅是枚举值的幕后重复使用: System.Reflection.FieldInfo有一个公开定义的属性称为IsPinvokeImpl,它专门检查此实现标志是否已设置。
有趣的是,MethodInfo类甚至没有这个属性 - 必须从MethodImplementationFlags属性中确定。
问题:
字段实际上可以是PInvoke实现的吗,还是这只是.NET框架中平衡字段装饰和方法装饰的存根实现?
如果可能的话,这个功能可以用C#实现吗?还是需要C++/CLI?
2个回答

7
当您查看FieldAttributes的MSDN描述时,您会发现它被记录为“保留以备将来使用”。 未来尚未到来,因此其意图尚未确定。
像FieldAttributes这样的类型并不是任意的,它们遵循CLI规范。 Ecma-335明确了.NET程序集中的元数据应该是什么样子以及应该如何解释。 这个文档揭示了一个有趣的问题。
第II.16.1章描述了字段属性,您将在元数据标记和FieldAttributes枚举之间看到一个紧密的匹配。 但请注意,pinvokeimpl在该章节中缺失
第II.23.1.5章提供了属性的具体值,其中包括PInvokeImpl,其值为0x2000。 描述是“实现通过PInvoke转发”。 与II.23.1.10进行比较,描述方法属性。 它与字段属性有许多共同点。
这看起来很像复制/粘贴错误 :)
深入研究 .NET Framework 源代码后,CLR 和 jitter 只考虑方法上的 pinvokeimpl。然而,C# 编译器似乎基于 CLI 规范,并实际设置了该属性。如果在字段而不是方法上调用此函数,则会在 emit.cpp 中出现 RegMeta::_DefinePinvokeMap() 函数中设置该属性的情况。但这种情况从未发生过。

3

来自FieldAttributes:

PinvokeImpl 保留以备将来使用。

因此,我会说:

问:字段是否实际上可以进行PInvoke实现?

答:不行。


+1 鼓励第一个正确回答问题的人,但我必须接受 Hans 的回答,因为他提供了关于 ECMA 规范和 .NET 源代码的额外见解。 - nicholas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接