2013-05-16 8 views
15

Quando l'uso ILSpy per controllare il codice di System.String, ho trovato ci sono alcuni metodi contrassegnati come MethodImplOptions.InternalCall quali:Come visualizzare il codice del metodo contrassegnato come MethodImplOptions.InternalCall?

[SecurityCritical] 
[MethodImpl(MethodImplOptions.InternalCall)] 
internal static extern int nativeCompareOrdinalEx(string strA, int indexA, string strB, int indexB, int count); 

So MethodImplOptions.InternalCall significa questo metodo è implementato nativamente dal linguaggio comune runtime al codice ottimizzato per migliorare le prestazioni.

La mia domanda è: è che comunque ci può consentire di vedere il codice contrassegnato come MethodImplOptions.InternalCall?

+3

Si dovrà guardare il codice C sottostante. Anche questo viene gestito in modo diverso tra framework, ovvero normale vs micro. – leppie

+0

È possibile ottenere "Sorgente condivisa" da Microsoft per molti pezzi del CLR. Non ho controllato ma penso che l'implementazione di 'System.String' dovrebbe essere inclusa - sia gestita che parti native. Vedi http://referencesource.microsoft.com/ per i dettagli –

+1

@ BenVoigt grazie per le vostre informazioni. Ricevo il codice sorgente da Microsoft e nel file di origine di String contiene i seguenti commenti: '** Scopo: la tua classe String preferita. I metodi nativi ** sono implementati in StringNative.cpp'. Tuttavia, sembra che MS non abbia reso pubblico questo file. – 2power10

risposta

12

Avrete bisogno del codice sorgente per il CLR per vedere l'implementazione di questi metodi. È un po 'difficile da trovare, Microsoft non lo pubblica e non è coperto dalla Reference Source.

Fintanto che il metodo è "vecchio", disponibile da .NET 2.0, è possibile eseguire uno scatto dal SSCLI20 source code. Con un rischio diverso da zero vedrete ovviamente una versione obsoleta del codice. Ma abbastanza buono per avere un'idea di ciò che sembra e spesso ancora preciso.

Il punto di partenza per iniziare la ricerca del codice è il file di codice sorgente clr/src/vm/ecall.cpp. Contiene le tabelle in cui il jitter ricerca i metodi interni. La sezione che è rilevante per nativeCompareOrdinalEx() appare così:

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.. 
} 

Si noti come il FCFuncElement ha il nome del metodo come una stringa e un puntatore a funzione per il metodo C++ che implementa la chiamata interna. Fare un grepping dell'albero del codice sorgente ti porta quindi a clr/src/vm/comstring.cpp. Non annoierò tutti con il codice C++, ma dai un'occhiata.

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

Ricerca di CaseInsensitiveCompHelper() e FastCompareStringHelperAligned() vi porta alle implementazioni reali dei, rispettivamente, funzioni di confronto case-insensitive e giurisprudenza sensibili nello stesso file di codice sorgente.

L'unica altra cosa notevole di questo è che CLR versione 4 ha apportato alcune modifiche a questo meccanismo. Aggiunta di molti nuovi metodi interni e supporto di un meccanismo di interoperabilità aggiuntivo completamente diverso attraverso un attributo [DllImport] per una falsa DLL chiamata "QCall". Non c'è un buon modo per vedere la fonte di queste aggiunte che io conosca.


UPDATE: fonte è ora disponibile dal CoreCLR project. La tabella è stata spostata da ecall.cpp in ecalllist.h, i meccanismi sono sempre gli stessi. Tieni presente che questa è la versione .NETCore del CLR, l'origine della versione desktop è ancora closed-source. Tuttavia, è probabile che le due versioni abbiano molto in comune.

1

Come dice la stringa di aiuto, sono "implementati nel CLR stesso", quindi è necessario consultare i suoi sorgenti C++ o il suo smontaggio.

In generale, i file che compongono il motore CLR sono alcune DLL native nella cartella %WINDIR%\Microsoft.NET\Framework\<.NET engine version>, per lo più mscor*.dll e clr.dll. La radice .NET DLL, mscoree.dll, è in System32 ma sembra funzionare solo come un launcher.

Poiché le implementazioni del metodo InternalCall sono dettagli di implementazione, non è possibile garantire che tali metodi siano implementati in modo coerente, ad es.che c'è anche qualche registro globale di loro.

E.g. il disassemblaggio mostra che i metodi nativi di .NET 4 System.String sono implementati in clr.dll e fanno riferimento in una struttura simile a una directory mentre System.Deployment.Application.NativeMethods.IClrRuntimeInfo è supportato dalla classe COM CLRRuntimeInfoImpl in mscoreei.dll, i metodi sono semplicemente le sue funzioni virtuali.

Problemi correlati