因此,当我遇到一些奇怪的事情时,今天我在ILSpy上浏览以更好地了解.NET如何在外部方法上执行DllImports。
当搜索对PInvokeImpl
枚举中定义的枚举值System.Reflection.MethodAttributes
的引用时,我注意到System.Reflection.FieldAttributes
中的匹配定义。
可以肯定的是,这似乎不仅仅是幕后的枚举值重用:System.Reflection.FieldInfo
具有一个公开定义的属性 IsPinvokeImpl
,它专门检查是否设置了此实现标志。
有趣的是,MethodInfo
类甚至没有此属性-必须由MethodImplementationFlags
属性确定。
问题:
字段是否实际上可能是PInvoke实现的,或者这仅仅是.NET框架中的 stub 实现,目的是在字段修饰和方法修饰之间取得平衡?
如果可能,是否可以用C#完成,还是这是需要C++/CLI的功能?
最佳答案
当您查看Field属性的MSDN描述时,您会看到它记录为“保留以供将来使用”。那个 future 还没有到来,所以它的意图还没有确定。
诸如FieldAttributes之类的类型不是任意的,它们遵循CLI规范。 Ecma-335明确了.NET程序集中元数据的外观以及应如何解释。该文档确实揭示了一个有趣的怪癖。
第II.16.1章介绍了字段属性,您将看到元数据标记和FieldAttributes枚举之间的紧密匹配。但是请注意,该章缺少pinvokeimpl
。
第II.23.1.5章提供了属性的特定值,它具有PInvokeImpl,其值为0x2000。描述为“通过PInvoke转发实现”。与II.23.1.10相比,描述了方法属性。它具有许多与字段属性相同的值。
这看起来很像复制/粘贴错误:)
深入研究.NET Framework源代码,CLR和抖动仅考虑pinvokeimpl方法。但是,C#编译器似乎基于CLI规范,并且实际上是在设置属性。出现在emit.cpp的RegMeta::_ DefinePinvokeMap()函数中,如果为字段而不是方法调用此函数,它将设置属性。那从来没有真正发生过。
关于c# - PInvoke实地执行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30620712/