CoreCLR Host源码分析(C++)
废话不多说,直接上源码:
1.在托管程序集里面执行方法
HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId,//通过CreateAppDomainWithManager创造的domainid
LPCWSTR pwzAssemblyPath,//要托管的.net core DLL 路径
int argc, //传递进来参数个数
LPCWSTR* argv,//传递进来参数数组
DWORD *pReturnValue)//指示函数执行的结果标记
{
CONTRACTL
{
THROWS; // Throws...as we do not want it to swallow the managed exception
ENTRY_POINT;
}
CONTRACTL_END; // This is currently supported in default domain only
if (dwAppDomainId != DefaultADID) //如果不等于默认defaultADID 直接返回失败标记
return HOST_E_INVALIDOPERATION; // No point going further if the runtime is not running...
if (!IsRuntimeActive() || !m_fStarted) //如果 coreclr host 没有在运行或者m_fstarted标记没有被启动,返回失败标记
{
return HOST_E_CLRNOTAVAILABLE;
} if(!pwzAssemblyPath) //如果托管的DLL为空,返回
return E_POINTER; if(argc < 0)//如果参数个数小于零,返回
{
return E_INVALIDARG;
} if(argc > 0 && argv == NULL)//如果参数个数大于零且参数数组等于零,返回
{
return E_INVALIDARG;
} HRESULT hr = S_OK; //初始化hr AppDomain *pCurDomain = SystemDomain::GetCurrentDomain(); //获取到当前appdomain的实例 Thread *pThread = GetThread(); //获取到当前进程指针
if (pThread == NULL) //如果进程指针为零
{
pThread = SetupThreadNoThrow(&hr);
if (pThread == NULL)
{
goto ErrExit;
}
} if(pCurDomain->GetId().m_dwId != DefaultADID)//如果当前进程的ID不等于defaultadid返回
{
return HOST_E_INVALIDOPERATION;
} INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
INSTALL_UNWIND_AND_CONTINUE_HANDLER; _ASSERTE (!pThread->PreemptiveGCDisabled()); Assembly *pAssembly = AssemblySpec::LoadAssembly(pwzAssemblyPath); //加载传递过来的托管程序集,并且实例化 #if defined(FEATURE_MULTICOREJIT)
pCurDomain->GetMulticoreJitManager().AutoStartProfile(pCurDomain);
#endif // defined(FEATURE_MULTICOREJIT) {
GCX_COOP(); // Here we call the managed method that gets the cmdLineArgs array.
SetCommandLineArgs(pwzAssemblyPath, argc, argv);//设置命令行参数 PTRARRAYREF arguments = NULL;
GCPROTECT_BEGIN(arguments); arguments = (PTRARRAYREF)AllocateObjectArray(argc, g_pStringClass);//分配内存
for (int i = 0; i < argc; ++i)
{
STRINGREF argument = StringObject::NewString(argv[i]);//转换参数
arguments->SetAt(i, argument);//设置参数数组标记
} DWORD retval = pAssembly->ExecuteMainMethod(&arguments, TRUE /*waitForOtherThreads */); //执行需要托管的method
if (pReturnValue) //如果返回标记不为空
{
*pReturnValue = retval;//赋值
} GCPROTECT_END(); } UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP; ErrExit: //如果错误,调到errexit ,返回HR return hr;
}
2.利用非托管加载程序集
Assembly *AssemblySpec::LoadAssembly(LPCWSTR pFilePath) // 传递托管程序集路径
{
CONTRACT(Assembly *)
{
THROWS;
GC_TRIGGERS;
MODE_ANY;
PRECONDITION(CheckPointer(pFilePath));
POSTCONDITION(CheckPointer(RETVAL));
INJECT_FAULT(COMPlusThrowOM(););
}
CONTRACT_END; AssemblySpec spec; //初始化assemblyspec 类
spec.SetCodeBase(pFilePath); //设置类的托管程序集路径
RETURN spec.LoadAssembly(FILE_LOADED); //设置类的加载方式为 文件加载
} DomainAssembly *AssemblySpec::LoadDomainAssembly(FileLoadLevel targetLevel, //加载方式,为文件加载,另外三个参数都为空
BOOL fThrowOnFileNotFound,
BOOL fRaisePrebindEvents,
StackCrawlMark *pCallerStackMark)
{
CONTRACT(DomainAssembly *)
{
INSTANCE_CHECK;
THROWS;
GC_TRIGGERS;
MODE_ANY;
POSTCONDITION((!fThrowOnFileNotFound && CheckPointer(RETVAL, NULL_OK))
|| CheckPointer(RETVAL));
INJECT_FAULT(COMPlusThrowOM(););
}
CONTRACT_END; ETWOnStartup (LoaderCatchCall_V1, LoaderCatchCallEnd_V1); //初始化一些宏定义
AppDomain* pDomain = GetAppDomain(); //获取当前 appdomain 的实例 DomainAssembly *pAssembly = nullptr; //声明并赋值一个 domainassembly ICLRPrivBinder * pBinder = GetHostBinder(); //获取到 iclrprivbinder 对象 // If no binder was explicitly set, check if parent assembly has a binder.
if (pBinder == nullptr) //如果 pbinder等于零
{
pBinder = GetBindingContextFromParentAssembly(pDomain); //获取到父类和注入的一些方法
} if (pBinder != nullptr)//如果获取到了
{
ReleaseHolder<ICLRPrivAssembly> pPrivAssembly;
HRESULT hrCachedResult;
if (SUCCEEDED(pBinder->FindAssemblyBySpec(GetAppDomain(), this, &hrCachedResult, &pPrivAssembly)) &&
SUCCEEDED(hrCachedResult))//用pbinder找到appdomain 的pprivassembly
{
pAssembly = pDomain->FindAssembly(pPrivAssembly);//利用找到的pprivassembly,pdomain调用然后赋值给要返回的程序集
}
} if ((pAssembly == nullptr) && CanUseWithBindingCache()) //如果为空
{
pAssembly = pDomain->FindCachedAssembly(this);//pdomain带上当前类的实例去缓存里面找当前的程序集
} if (pAssembly)//如果找到
{
pDomain->LoadDomainFile(pAssembly, targetLevel); //以文件方式加载程序集
RETURN pAssembly; //然后返回
} PEAssemblyHolder pFile(pDomain->BindAssemblySpec(this, fThrowOnFileNotFound, fRaisePrebindEvents, pCallerStackMark));//如果上面所有步骤都不行,实例化一个peassemblyholder,
if (pFile == NULL)
RETURN NULL; pAssembly = pDomain->LoadDomainAssembly(this, pFile, targetLevel);//利用这个实例化的peassemblyholder和this指针,以及文件加载的方式去获取程序集 RETURN pAssembly; //返回程序集
}
CoreCLR Host源码分析(C++)的更多相关文章
- Orchard源码分析(5):Host相关(Orchard.Environment.DefaultOrchardHost类)
概述 Host 是应用程序域级的单例,代表了Orchard应用程序.其处理应用程序生命周期中的初始化.BeginRequest事件.EndRequest事件等. 可以简单理解为HttpApplicat ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- ABP源码分析七:Setting 以及 Mail
本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...
- ABP源码分析三十五:ABP中动态WebAPI原理解析
动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能, ...
- MyCat源码分析系列之——前后端验证
更多MyCat源码分析,请戳MyCat源码分析系列 MyCat前端验证 MyCat的前端验证指的是应用连接MyCat时进行的用户验证过程,如使用MySQL客户端时,$ mysql -uroot -pr ...
- gRPC源码分析0-导读
gRPC是Google开源的新一代RPC框架,官网是http://www.grpc.io.正式发布于2016年8月,技术栈非常的新,基于HTTP/2,netty4.1,proto3.虽然目前在工程化方 ...
- YARN DistributedShell源码分析与修改
YARN DistributedShell源码分析与修改 YARN版本:2.6.0 转载请注明出处:http://www.cnblogs.com/BYRans/ 1 概述 2 YARN Distrib ...
- [dpdk] 熟悉SDK与初步使用 (三)(IP Fragmentation源码分析)
对例子IP Fragmentation的熟悉,使用,以及源码分析. 功能: 该例子的功能有二: 一: 将IP分片? 二: 根据路由表,做包转发. 路由表如下: IP_FRAG: Socket : ad ...
- docker 源码分析 四(基于1.8.2版本),Docker镜像的获取和存储
前段时间一直忙些其他事情,docker源码分析的事情耽搁了,今天接着写,上一章了解了docker client 和 docker daemon(会启动一个http server)是C/S的结构,cli ...
随机推荐
- ASP.NET MVC/Core表单提交后台模型二级属性验证问题
起因 这个是网友在官网论坛的提问:https://fineui.com/bbs/forum.php?mod=viewthread&tid=22237 重新问题 本着务实求真的态度,我们先来复现 ...
- spring boot + druid + mybatis + atomikos 多数据源配置 并支持分布式事务
文章目录 一.综述 1.1 项目说明 1.2 项目结构 二.配置多数据源并支持分布式事务 2.1 导入基本依赖 2.2 在yml中配置多数据源信息 2.3 进行多数据源的配置 三.整合结果测试 3.1 ...
- SSM框架学习笔记_第1章_SpringIOC概述
第1章 SpringIOC概述 Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 1.1 控制反转IOC IOC(inversion of controller)是一种概念 ...
- 借助URLOS快速安装WordPress
### 简介 WordPress是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统.WordPress具有插件架构和模板系统.截至2018年4月,排名前1000万的网站超过30.6%使 ...
- 利用Jmeter模拟Github登录
最近学习了Jmeter的简单操作,很想找点东西来实战一下,因为我之前写过一篇通过Python模拟登录的文章,于是便想尝试下学习通过Jmeter来模拟登录. 本人环境:Jmeter5.1.1 关于Git ...
- spark 源码分析之十三 -- SerializerManager剖析
对SerializerManager的说明: 它是为各种Spark组件配置序列化,压缩和加密的组件,包括自动选择用于shuffle的Serializer.spark中的数据在network IO 或 ...
- 深入学习Spring框架(三)- AOP面向切面
1.什么是AOP? AOP为 Aspect Oriented Programming 的缩写,即面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术..AOP是OOP的延续, ...
- ElasticStack学习(八):ElasticSearch索引模板与聚合分析初探
一.Index Template与Dynamic Template的概念 1.Index Template:它是用来根据提前设定的Mappings和Settings,并按照一定的规则,自动匹配到新创建 ...
- Linux查看空间大小的命令
在linux中,常用查看空间大小的命令有df.du,下面依次介绍一下. df 命令是linux系统上以磁盘分区为单位来查看文件系统的命令,后面可以加上不同的参数来查看磁盘的剩余空间信息.Linux d ...
- I/O:Writer
Writer: Writer append(char c) :将指定字符添加到此 writer. Writer append(CharSequence csq) :将指定字符序列添加到此 writer ...