PInvoke字段实现

nic*_*las 5 .net c# pinvoke

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

当搜索枚举PInvokeImpl中定义的枚举值的System.Reflection.MethodAttributes引用时,我注意到了匹配的定义System.Reflection.FieldAttributes.

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

有趣的是,这个MethodInfo班级甚至没有这个属性 - 必须从MethodImplementationFlags酒店确定.

题:

实际上是否可以将字段实现为PInvoke,或者这只是.NET框架中的存根实现,以实现字段装饰和方法装饰之间的平衡?

如果可能,可以在C#中完成,还是这是一个需要C++/CLI的功能?

Han*_*ant 6

当您查看FieldAttributes的MSDN描述时,您会看到它记录为"保留供将来使用".那个未来尚未到来,所以它的意图没有被确定下来.

FieldAttributes之类的类型不是任意的,它们遵循CLI规范. Ecma-335指出.NET程序集中的元数据需要看起来是什么以及如何解释它.这份文件确实揭示了一个有趣的怪癖.

第II.16.16章描述了字段属性,您将看到元数据标记与FieldAttributes枚举之间的紧密匹配.但是,请注意pinvokeimpl缺少在这一章.

第II.2.2.1.1节给出了属性的具体值,它具有值为0x2000的PInvokeImpl.描述是"通过PInvoke转发实现".与II.23.1.10比较,描述了方法属性.它与字段属性有许多共同之处.

这看起来很像复制/粘贴bug :)

通过.NET Framework源代码深入挖掘,CLR和抖动只考虑了方法上的pinvokeimpl.但是,C#编译器似乎基于CLI规范并实际设置了该属性.出现在emit.cpp,RegMeta :: _ DefinePinvokeMap()函数中,如果为字段而不是方法调用此函数,它将设置该属性.那实际上从未发生过.