如何查看标记为MethodImplOptions.InternalCall的方法代码?

时间:2013-05-16 04:36:11

标签: c# .net clr

当使用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的代码吗?

3 个答案:

答案 0 :(得分:13)

您需要CLR的源代码才能看到这些方法的实现。这有点难以实现,微软不发布它,参考源不包括它。

只要该方法是“旧的”,从.NET 2.0开始就可以使用,那么你可以从SSCLI20 source code获取它。如果风险非零,那么您将会看到过时的代码版本。但足够好,可以了解它的外观并且通常仍然准确。

开始搜索代码的起点是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 project获取来源。该表从ecall.cpp转移到ecalllist.h,机制仍然相同。请记住,这是CLR的.NETCore版本,桌面版本源仍然是封闭源代码。然而,这两个版本可能有很多共同之处。

答案 1 :(得分:3)

从现在开始CoreCLR is open source,我们就可以查看内部代码了。

您可以在stringnative.cpp中搜索COMString::CompareOrdinalEx关键字以查看内部实施。

答案 2 :(得分:1)

正如帮助字符串所示,它们是“在CLR本身中实现的”,因此您需要查阅其C ++源代码或反汇编。

通常,构成CLR引擎的文件是%WINDIR%\Microsoft.NET\Framework\<.NET engine version>文件夹中的一些本机DLL,主要是mscor*.dllclr.dll。根.NET DLL mscoree.dll位于System32中,但它似乎只是一个启动器。

由于InternalCall方法实现是实现细节,因此无法保证这些方法以一致的方式实现,例如甚至还有一些全球性的注册表。

E.g。反汇编表明,.NET 4 System.String的本机方法在clr.dll中实现,并在类似目录的结构中引用,而System.Deployment.Application.NativeMethods.IClrRuntimeInfoCLRRuntimeInfoImpl COM类支持{ {1}},这些方法只是虚函数。