如何找到public extern bool Equals(String value)的實現代碼?[C#, C++, BCL, CLR]

來源:互聯網
上載者:User

如何找到public extern bool Equals(String value)的實現代碼?[C#, C++, BCL, CLR]

 

Written by Allen Lee

 

Q:在微軟提供的Rotor原始碼中,我發現String.Equals(String value)的代碼只有下面兩行:

// Code #01
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern bool Equals(String value);

那麼,在哪裡可以找到該方法的實現代碼呢?

A:開啟Rotor原始碼的sscli\clr\src\vm\ecall.cpp檔案,搜尋“Equals”關鍵字,你將找到如下所示的數群組成員:

// Code #02
static ECFunc gStringFuncs[] = {

    // Other members here

    {FCFuncElement("Equals", &gsig_IM_Str_RetBool, (LPVOID)COMString::EqualsString)},

    // Other members here
};

從該數群組成員中,我們可以得知我們要尋找的就是COMString::EqualsString函數。那麼,ComString::EqualsString函數的實現代碼又在哪裡呢?

開啟Rotor原始碼的sscli\clr\src\vm\comstring.cpp檔案,搜尋“COMString::EqualsString”關鍵字,怎麼樣,找到實現代碼了嗎?

Q:是的,我找到了:

// Code #03
FCIMPL2(INT32, COMString::EqualsString, StringObject* thisStr, StringObject* valueStr) 
{
    VALIDATEOBJECTREF(thisStr);
    VALIDATEOBJECTREF(valueStr);

    INT32 ret = false;
    if (NULL==thisStr)
        FCThrow(kNullReferenceException);
        
    if (!valueStr)
    {
        FC_GC_POLL_RET();
        return ret;
    }

    ret = WcharCompareHelper (STRINGREF(thisStr), STRINGREF(valueStr));
    FC_GC_POLL_RET();
    return ret;
}
FCIMPLEND

你能否簡單說明一下?

A:Code #03的函數的定義使用了宏(Macro)。在sscli\clr\src\vm\fcall.h檔案中,你會找到如下語句:

// Code #04
#define FCDECL2(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(a1, a2)

這就是該函數的宏定義。於是,上面你所找到的C++代碼就可以展開為:

// Code #05
INT32 F_CALL_CONV COMString::EqualsString(StringObject* thisStr, StringObject* valueStr)
{
    // 
}

Code #04所示的宏是對應著x86體系的,對於非x86體系,該函數的宏定義為:

// Code #06
#define FCIMPL2(rettype, funcname, a1, a2) rettype funcname(a1, a2) { FCIMPL_PROLOG(funcname)

另外,該函數其實把真正的比較工作交給了WcharCompareHelper函數,你可以在同一個檔案(comstring.cpp)中找到它的真身:

// Code #07
bool WcharCompareHelper (STRINGREF thisStr, STRINGREF valueStr)
{
    DWORD *thisChars, *valueChars;
    int thisLength, valueLength;

    //Get all of our required data.
    RefInterpretGetStringValuesDangerousForGC(thisStr, (WCHAR**)&thisChars, &thisLength);
    RefInterpretGetStringValuesDangerousForGC(valueStr, (WCHAR**)&valueChars, &valueLength);

    //If they're different lengths, they're not an exact match.
    if (thisLength!=valueLength) {
        return false;
    }
  
    // Loop comparing a DWORD (2 WCHARs) at a time.
    while ((thisLength -= 2) >= 0)
    {
        if (*thisChars != *valueChars)
            return false;
        ++thisChars;
        ++valueChars;
    }

    // Handle an extra WCHAR.
    if (thisLength == -1)
        return (*((WCHAR *) thisChars) == *((WCHAR *) valueChars));

    return true;
}

至此,你已經找到Rotor的String.Equals(String value)的實現演算法了。

Q:ecall.cpp檔案是用來幹什麼的?

A:該檔案包含著為數眾多的數組,這些數組實質上充當一個表的角色,用於把標記了[MethodImplAttribute(MethodImplOptions.InternalCall)]屬性的方法映射為非託管的C++實現。其中,數組的成員實際上也使用了宏。Code #02中的

// Code #08
FCFuncElement("Equals", &gsig_IM_Str_RetBool, (LPVOID)COMString::EqualsString)

就對應著Code #09的宏定義:

// Code #09
#define FCFuncElement(A,B,C) A, B, C, NULL, CORINFO_INTRINSIC_Illegal

Q:fcall.h檔案又是用來幹什麼的?

A:該檔案也定義了為數眾多的宏,這些宏充當著“函數模板”的角色,用於把簽名相類似的函數組織起來,並以統一的方式展開。該檔案開頭還留有相關的注釋,用於說明這些宏的作用、工作原理以及相關注意事項。

Q:什麼情況下,我們可以使用這種方法來尋找Rotor BCL中沒有給出具體實現的方法代碼?

A:我們知道,沒有給出具體實現代碼的方法,需要添加extern以表明該實現在別的某處可以找到,一般情況下,該修飾符與DllImportAttribute結合使用:

// Code #10
[DllImport("uxtheme.dll")]
static public extern int SetWindowTheme(IntPtr hWnd, StringBuilder AppID, StringBuilder ClassID);
static public void DisableWindowsXPTheme(IntPtr hWnd) 
{
    // Disable using the Window XP Theme for the Window handle
    // passed as a parameter
    StringBuilder applicationName = new StringBuilder(" ", 1); 
    StringBuilder classIDs = new StringBuilder(" " , 1); 
    Win32.SetWindowTheme(hWnd, applicationName, classIDs);
}

這樣,.NET就會自動從uxtheme.dll那裡尋找對應的實現代碼,這種調用方式叫做PInvoke。當然,這種情況下,你是無法擷取具體的實現代碼了。

然而,BCL中有相當一部分方法使用extern和MethodImplAttribute來修飾的,此時,只要給MethodImplAttribute的建構函式傳遞的參數是MethodImplOptions.InternalCall枚舉,就代表著你可以使用我介紹給你的方法來尋找實現代碼了。底線是你擁有這些底層非託管原始碼讓你尋找!

Q:MethodImplAttribute用來幹什麼的?

A:該Attribute位於System.Runtime.CompilerServices命名空間,結合MethodImplOptions枚舉來使用,用於描述方法或者構造器的實現方式。Code #01中的[MethodImplAttribute(MethodImplOptions.InternalCall)]則用於說明該方法的具體實現可以從CLR內部找到。該屬性實質上是一種偽屬性(pseudo-attribute),有別於普通的自訂屬性,它是以位的形式儲存在中繼資料表(metadata table)中的,並且只能通過MethodBase.GetMethodImplementationFlags來擷取相關的資訊。

Q:從上面的討論,我們可以瞭解到EqualsString函數是屬於一個叫ComString的類,那麼這個ComString類與BCL中的String類有什麼關係?

A:Good question!Rotor BCL中的String.cs中我們可以找到這樣一句話:

Actual implementations are in String.cpp

事實上,這個String.cpp就是comstring.cpp;同樣,在comstring.cpp中,我們也可以看到這樣一句話:

Purpose: The implementation of the String class.

我們發現String.cs中很多方法都沒有提供具體的實現代碼,而這些方法的真身其實就隱藏在comstring.cpp中。

Q:最後,對於探索.NET內部原理,你有什麼好推薦?

A:其實微軟所提供的Rotor原始碼以及Mono這個開源項目裡面已經有很豐富的注釋以供學習之用。當然,我還是要為大家介紹幾個有用的串連:

  • Rotor Source code:該網站以網頁的的形式把Rotor BCL的代碼展示出來,相關的代碼使用C#語言。
  • Rotor VM Documentation:該網站以網頁的形式把Rotor VM的代碼展示出來,相關的代碼使用C++語言。
  • Jason Whittington, Shared Source CLI Provides Source Code for a FreeBSD Implementation of .NET。

希望這些資料能夠協助大家更好的探索.NET的內部原理。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.