如何查看标记为MethodImplOptions.InternalCall的方法代码?
当使用ILSpy检查System.String的代码时,我发现有一些方法被标记为MethodImplOptions.InternalCall,例如:
[SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern int nativeCompareOrdinalEx(string strA, int indexA, string strB, int indexB, int count);
我知道MethodImplOptions.InternalCall意味着这个方法由公共语言运行库本地实现,以优化代码以提高性能。
我的问题是:无论如何,这可以让我们看到标记为MethodImplOptions.InternalCall的代码吗?
您需要CLR的源代码才能看到这些方法的实现。 这有点难以实现,微软不会发布它并且它不在参考源中。
只要该方法是“旧的”,从.NET 2.0开始就可以使用,那么您将从SSCLI20源代码中获取它 。 如果风险非零,那么您将会看到过时的代码版本。 但足以让人知道它看起来像什么,而且往往仍然准确。
开始搜索代码的起点是clr / src / vm / ecall.cpp源代码文件。 它包含抖动搜索内部方法的表。 与nativeCompareOrdinalEx()相关的部分如下所示:
FCFuncStart(gStringFuncs) FCDynamic("FastAllocateString", CORINFO_INTRINSIC_Illegal, ECall::FastAllocateString) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayStartLengthManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrStartLengthManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_Char_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharCountManaged) FCFuncElement("nativeCompareOrdinal", COMString::FCCompareOrdinal) // <=== Here FCFuncElement("nativeCompareOrdinalWC", COMString::FCCompareOrdinalWC) FCIntrinsic("get_Length", COMString::Length, CORINFO_INTRINSIC_StringLength) // etc.. }
注意FCFuncElement如何将方法名称作为字符串,以及指向实现内部调用的C ++方法的函数指针。 点击源代码树然后转到clr / src / vm / comstring.cpp。 我不会让所有人都厌倦C ++代码,只是看看你自己。
/*================================CompareOrdinal===============================*/ FCIMPL3(INT32, COMString::FCCompareOrdinal, StringObject* strA, StringObject* strB, CLR_BOOL bIgnoreCase) { // Yadayada //... }
搜索CaseInsensitiveCompHelper()和FastCompareStringHelperAligned()会将您带到相同源代码文件中的不区分大小写和区分大小写的比较函数的实际实现。
唯一值得注意的是CLR版本4对此机制进行了一些更改。 添加许多新的内部方法,并通过名为“QCall”的假DLL的[DllImport]属性支持完全不同的附加互操作机制。 没有什么好方法可以看到我所知道的这些新增内容的来源。
更新:现在可以从CoreCLR项目获得源代码。 该表从ecall.cpp转移到ecalllist.h,机制仍然相同。 请记住,这是CLR的.NETCore版本,桌面版本源仍然是封闭源代码。 然而,这两个版本可能有很多共同之处。
由于现在CoreCLR是开源的 ,所以我们可以查看内部代码。
您可以在stringnative.cpp中搜索COMString::CompareOrdinalEx
关键字以查看内部实现。
正如帮助字符串所说,它们“在CLR本身中实现”,因此您需要查阅其C ++源代码或反汇编代码。
通常,组成CLR引擎的文件是%WINDIR%\Microsoft.NET\Framework\<.NET engine version>
文件夹中的一些本机DLL,主要是mscor*.dll
和clr.dll
。 根.NET DLL, mscoree.dll
,在System32
但它似乎只作为启动器。
由于InternalCall
方法实现是实现细节,因此无法保证这些方法以一致的方式实现,例如,甚至还有一些全局注册表。
例如,反汇编表明.NET 4 System.String
的本机方法在clr.dll
中实现,并在类似目录的结构中引用,而System.Deployment.Application.NativeMethods.IClrRuntimeInfo
由CLRRuntimeInfoImpl
COM类mscoreei.dll
,这些方法只是它的虚函数。