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

2po*_*r10 17 .net c# 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);
Run Code Online (Sandbox Code Playgroud)

我知道MethodImplOptions.InternalCall意味着该方法由公共语言运行库本地实现,以优化代码以提高性能.

我的问题是:无论如何,是否可以让我们看到标记为MethodImplOptions.InternalCall的代码?

Han*_*ant 13

您需要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..
}
Run Code Online (Sandbox Code Playgroud)

请注意FCFuncElement如何将方法名称作为字符串,以及指向实现内部调用的C++方法的函数指针.点击源代码树然后转到clr/src/vm/comstring.cpp.我不会用C++代码让每个人都厌烦,只要看看你自己.

/*================================CompareOrdinal===============================*/
FCIMPL3(INT32, COMString::FCCompareOrdinal, StringObject* strA, StringObject* strB, CLR_BOOL bIgnoreCase) {
    // Yadayada
    //...
}
Run Code Online (Sandbox Code Playgroud)

搜索CaseInsensitiveCompHelper()和FastCompareStringHelperAligned()会将您带到相同源代码文件中的不区分大小写和区分大小写的比较函数的实际实现.

唯一值得注意的是CLR版本4对此机制进行了一些更改.添加许多新的内部方法,并通过名为"QCall"的假DLL的[DllImport]属性支持完全不同的附加互操作机制.我知道这些添加的源代码没有好办法.


更新:现在可以从CoreCLR项目获得源代码.该表从ecall.cpp转移到ecalllist.h,机制仍然相同.请记住,这是CLR的.NETCore版本,桌面版本源仍然是封闭源代码.然而,这两个版本可能有很多共同之处.


2po*_*r10 3

由于现在CoreCLR是开源的,所以我们可以查看内部代码。

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