字段上的PInvoke实现

本文关键字:实现 PInvoke 字段 | 更新日期: 2023-09-27 17:53:07

所以今天我正在浏览ILSpy,以便更好地理解。net如何在外部方法上执行DllImports,当我遇到一些奇怪的事情时:

在搜索对System.Reflection.MethodAttributes枚举中定义的枚举值PInvokeImpl的引用时,我注意到System.Reflection.FieldAttributes中有一个匹配的定义。

当然,这似乎不仅仅是一个幕后,枚举值的重用:System.Reflection.FieldInfo有一个名为IsPinvokeImpl的公共定义属性,它专门检查是否设置了这个实现标志。

有趣的是,MethodInfo类甚至没有这个属性——它必须从MethodImplementationFlags属性中确定。

问题:

一个字段是否有可能被PInvoke实现,或者这只是.NET框架中用于平衡字段装饰和方法装饰的存根实现?

如果可能的话,它可以在c#中完成吗,或者这是一个需要c++/CLI的功能?

字段上的PInvoke实现

当你查看fieldatattributes的MSDN描述时,你会看到它被记录为"Reserved for future use"。这个未来还没有到来,所以它的意图还没有确定。

像fieldatattributes这样的类型不是任意的,它们遵循CLI规范。Ecma-335确定了。net程序集中的元数据应该是什么样子,以及应该如何解释它。这个文档确实揭示了一个有趣的怪癖。

Chapter II.16.1描述了字段属性,你会看到元数据令牌和fieldatattributes枚举之间的紧密匹配。但是请注意,pinvokeimpl在该章中缺少。

Chapter II.23.1.5给出了属性的具体值,它有值为0x2000的PInvokeImpl。描述为"通过PInvoke转发实现"。相对于II.23.1.10,描述了方法属性。它有许多与字段属性相同的值。

这看起来很像一个复制/粘贴错误:)

在。net框架源代码中深入挖掘,CLR和jitter只考虑对方法的pinvokeimpl。然而,c#编译器似乎是基于CLI规范的,并实际设置了该属性。出现在emit.cpp, RegMeta::_DefinePinvokeMap()函数中,如果为字段而不是方法调用此函数,则将设置该属性。

From fielattributes:

PinvokeImpl保留将来使用

所以我要说:

Q:一个字段实际上可能被PInvoke实现吗

: