`
lovnet
  • 浏览: 6670867 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

如何找到public extern bool Equals(String value)的实现代码?[C#, C++, BCL, CLR]

阅读更多

如何找到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)]
publicexternboolEquals(Stringvalue);

那么,在哪里可以找到该方法的实现代码呢?

A:打开Rotor源代码的sscli\clr\src\vm\ecall.cpp文件,搜索“Equals”关键字,你将找到如下所示的数组成员:

//Code#02
staticECFuncgStringFuncs[]={

//Othermembershere

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

//Othermembershere
}
;

从该数组成员中,我们可以得知我们要寻找的就是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);

INT32ret
=false;
if(NULL==thisStr)
FCThrow(kNullReferenceException);

if(!valueStr)
{
FC_GC_POLL_RET();
returnret;
}


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

FCIMPLEND

你能否简单说明一下?

A:Code #03的函数的定义使用了宏(Macro)。在sscli\clr\src\vm\fcall.h文件中,你会找到如下语句:

//Code#04
#defineFCDECL2(rettype,funcname,a1,a2)rettypeF_CALL_CONVfuncname(a1,a2)

这就是该函数的宏定义。于是,上面你所找到的C++代码就可以展开为:

//Code#05
INT32F_CALL_CONVCOMString::EqualsString(StringObject*thisStr,StringObject*valueStr)
{
//
}

Code #04所示的宏是对应着x86体系的,对于非x86体系,该函数的宏定义为:

//Code#06
#defineFCIMPL2(rettype,funcname,a1,a2)rettypefuncname(a1,a2){FCIMPL_PROLOG(funcname)

另外,该函数其实把真正的比较工作交给了WcharCompareHelper函数,你可以在同一个文件(comstring.cpp)中找到它的真身:

//Code#07
boolWcharCompareHelper(STRINGREFthisStr,STRINGREFvalueStr)
{
DWORD
*thisChars,*valueChars;
intthisLength,valueLength;

//Getallofourrequireddata.
RefInterpretGetStringValuesDangerousForGC(thisStr,(WCHAR**)&thisChars,&thisLength);
RefInterpretGetStringValuesDangerousForGC(valueStr,(WCHAR
**)&valueChars,&valueLength);

//Ifthey'redifferentlengths,they'renotanexactmatch.
if(thisLength!=valueLength){
returnfalse;
}


//LoopcomparingaDWORD(2WCHARs)atatime.
while((thisLength-=2)>=0)
{
if(*thisChars!=*valueChars)
returnfalse;
++thisChars;
++valueChars;
}


//HandleanextraWCHAR.
if(thisLength==-1)
return(*((WCHAR*)thisChars)==*((WCHAR*)valueChars));

returntrue;
}

至此,你已经找到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
#defineFCFuncElement(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")]
staticpublicexternintSetWindowTheme(IntPtrhWnd,StringBuilderAppID,StringBuilderClassID);
staticpublicvoidDisableWindowsXPTheme(IntPtrhWnd)
{
//DisableusingtheWindowXPThemefortheWindowhandle
//passedasaparameter
StringBuilderapplicationName=newStringBuilder("",1);
StringBuilderclassIDs
=newStringBuilder("",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这个开源项目里面已经有很丰富的注释以供学习之用。当然,我还是要为大家介绍几个有用的连接:

希望这些资料能够帮助大家更好的探索.NET的内部原理。

分享到:
评论

相关推荐

    闪烁应用程序窗体,不用timer控件,C#源代码[DllImport("User32")] public static extern bool FlashWindow(IntPtr hWnd, bool bInvert); try

    闪烁应用程序窗体,不用timer控件,C#源代码[DllImport("User32")] public static extern bool FlashWindow(IntPtr hWnd, bool bInvert); try { int MyTimes = 50; int MyTime = 50; for (int MyCount = 0; ...

    通过avicap32.dll操作视频的类(C#)

    public static extern IntPtr capCreateCaptureWindow(string lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hwndParent, int nID); /************参数说明************* * * ...

    C# 中调用C++ DLL

    为了能用上原来的C++代码,只好研究下从C# 中调用DLL 首先必须要有一个声明,使用的是DllImport关键字: 包含DllImport所在的名字空间 using System.Runtime.InteropServices; public class XXXX{ [DllImport(...

    c#GetVideo

    public static extern bool capGetDriverDescriptionA(short wDriver, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpszName, int cbName, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpszVer, int ...

    学习总结:C++中extern “C”含义深层探索.doc

    看看就知道:学习总结:C++中extern “C”含义深层探索.doc

    【VS2010 C# 代码】获取鼠标所在位置的窗口句柄名称和文字及位置

    Microsoft Visual Studio 2010做的C#获取鼠标所在位置的窗口句柄名称和文字及位置实例,主要代码: [StructLayout(LayoutKind.Sequential)]//定义与API相兼容结构体,实际上是一种内存转换 public struct POINTAPI ...

    c# 用共享内存实现进程通信

    c# 用共享内存实现进程通信 开几个程序都可以访问同样的内存数据 ... public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);

    c# 计划关机。net

    internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool ...

    C#窗体实现热键控制窗口隐藏显示

    C#窗体实现热键控制窗口隐藏显示 主要类文件 class HotKey { //如果函数执行成功,返回值不为0。 //如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。 [DllImport("user32.dll", ...

    C# 自定义窗体的最大化、最小化和关闭按钮

    public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); public const int WM_SYSCOMMAND = 0x0112; public const int SC_MOVE = 0xF010; public const int HTCAPTION = 0x...

    C#读写INT文档

    private static extern bool WritePrivateProfileString ( string section ,string key , string val , string filePath ) ; //读ini文件(字符 [ DllImport ( \"kernel32\" ) ] private static extern ...

    C# CS版关机小程序

    internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool ...

    C# DllImport的用法

    大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比如Windows中的一些功能,C++中已经编写好的一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在的功能呢?...

    从指定文件byte[]内存数组加载非托管DLL API

    public extern static IntPtr GetProcAddress(IntPtr handle, String funcName); [DllImport("kernel.dll", EntryPoint = "MemFreeLibrary")] public extern static bool FreeLibrary(IntPtr handle); #...

    winfrom 本地时间同步为北京标准时间

    public static extern bool SetSystemTime(ref SYSTEMTIME time); [DllImport("Kernel32.dll")] public static extern bool SetLocalTime(ref SYSTEMTIME time); [DllImport("Kernel32.dll")] public static ...

    C++简单代码示例说明extern用法

    用一个简单C++代码示例来说明extern用法;

    【VS2010 C# 代码】实时监听鼠标位置

    Microsoft Visual Studio 2010做的C#简单的实时监听鼠标位置实例,主要代码: public class Win32Api { [StructLayout(LayoutKind.Sequential)] public class POINT { public int x; public int y; } [StructLayout...

    C#调用C++编写的DLL函数各种参数传递问题

    1. 不返回值的参数  C++ 原型: ...  public static extern bool SendNewSms(string phone,string msg);  2. 带返回值(char *)  C++原型:  BOOL GetCardErrorMessage(char *szErrorMessage , int

    c#读写ini文件 程序代码

    c#读写ini文件 以下程序是我为公司写的一个软件中的一部分代码. //==================创建INI文件读写函数====================== //调用kernel32.dll中的两个API:WritePrivateProfileString,...

    C# CS版关机小程序 关机小程序

    internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool ...

Global site tag (gtag.js) - Google Analytics