17

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

4

3 回答 3

13

您需要 CLR 的源代码来查看这些方法的实现。这有点难以获得,Microsoft 没有发布它,并且它不在参考源中。

只要该方法是“旧的”,自 .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++ 方法的函数指针。Grepping 源代码树然后将您带到 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 版本,桌面版本的源代码仍然是闭源的。然而,这两个版本可能有很多共同点。

于 2013-05-16T12:15:23.800 回答
3

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

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

于 2016-04-06T09:09:15.037 回答
1

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

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

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

例如,反汇编表明 .NET 4System.String的本机方法clr.dll在类似目录的结构中实现和引用,同时System.Deployment.Application.NativeMethods.IClrRuntimeInfo由 .NET 中的CLRRuntimeInfoImplCOM 类支持mscoreei.dll,这些方法只是它的虚拟函数。

于 2013-11-11T20:30:49.187 回答