如何找到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)的代码只有下面两行:



那么,在哪里可以找到该方法的实现代码呢?
A:打开Rotor源代码的sscli\clr\src\vm\ecall.cpp文件,搜索“Equals”关键字,你将找到如下所示的数组成员:











从该数组成员中,我们可以得知我们要寻找的就是COMString::EqualsString函数。那么,ComString::EqualsString函数的实现代码又在哪里呢?
打开Rotor源代码的sscli\clr\src\vm\comstring.cpp文件,搜索“COMString::EqualsString”关键字,怎么样,找到实现代码了吗?
Q:是的,我找到了:





















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


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






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


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






























至此,你已经找到Rotor的String.Equals(String value)的实现算法了。
Q:ecall.cpp文件是用来干什么的?
A:该文件包含着为数众多的数组,这些数组实质上充当一个表的角色,用于把标记了[MethodImplAttribute(MethodImplOptions.InternalCall)]属性的方法映射为非托管的C++实现。其中,数组的成员实际上也使用了宏。Code #02中的


就对应着Code #09的宏定义:


Q:fcall.h文件又是用来干什么的?
A:该文件也定义了为数众多的宏,这些宏充当着“函数模板”的角色,用于把签名相类似的函数组织起来,并以统一的方式展开。该文件开头还留有相关的注释,用于说明这些宏的作用、工作原理以及相关注意事项。
Q:什么情况下,我们可以使用这种方法来查找Rotor BCL中没有给出具体实现的方法代码?
A:我们知道,没有给出具体实现代码的方法,需要添加extern以表明该实现在别的某处可以找到,一般情况下,该修饰符与DllImportAttribute结合使用:











这样,.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的内部原理。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架