Core CLR Host 源码简单分析
在定制 CLR Host的时候,可以通过调用如下代码,来获取当前需要被宿主的程序调用入口:
hr = Host->CreateDelegate(
domainId,
L"Main,Version=1.0.0.0",
L"Main.Program", // Target managed type
L"Main", // Target entry point (static method)
(INT_PTR*)&pfnDelegate);
CreateDelegate 会进入到corhost.cpp里面
HRESULT CorHost2::CreateDelegate(
DWORD appDomainID,
LPCWSTR wszAssemblyName,
LPCWSTR wszClassName,
LPCWSTR wszMethodName,
INT_PTR* fnPtr)
{
WRAPPER_NO_CONTRACT; return _CreateDelegate(appDomainID, wszAssemblyName, wszClassName, wszMethodName, fnPtr);
}
然后_CreateDelegate 会CorHost2::_CreateDelegate,这个函数里面首先实例化了一个AssemblySpec,然后用传递过来的程序集名称初始化,通过AssemblySpec的LoadfAssembly实例化程序集。
获取程序集的类加载器,通过类加载器加载TypeHandle,传递的参数分别为程序集实例和ClassName。然后再通过MemberLoader::FindMethodByName获取到类里面的所需要查找的方法。
通过AppDomain的GetUMEntryThunkCache函数返回UMEntryThunk,最后通过UMEntryThunk->GetCode()返回要查找的函数指针。代码如下:
HRESULT CorHost2::_CreateDelegate(
DWORD appDomainID,
LPCWSTR wszAssemblyName,
LPCWSTR wszClassName,
LPCWSTR wszMethodName,
INT_PTR* fnPtr)
{ CONTRACTL
{
NOTHROW;
if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
ENTRY_POINT; // This is called by a host.
}
CONTRACTL_END; HRESULT hr=S_OK; EMPTY_STRING_TO_NULL(wszAssemblyName);
EMPTY_STRING_TO_NULL(wszClassName);
EMPTY_STRING_TO_NULL(wszMethodName); if (fnPtr == NULL)
return E_POINTER;
*fnPtr = NULL; if(wszAssemblyName == NULL)
return E_INVALIDARG; if(wszClassName == NULL)
return E_INVALIDARG; if(wszMethodName == NULL)
return E_INVALIDARG; if (!m_fStarted)
return HOST_E_INVALIDOPERATION; BEGIN_ENTRYPOINT_NOTHROW; BEGIN_EXTERNAL_ENTRYPOINT(&hr);
GCX_COOP_THREAD_EXISTS(GET_THREAD()); MAKE_UTF8PTR_FROMWIDE(szAssemblyName, wszAssemblyName);
MAKE_UTF8PTR_FROMWIDE(szClassName, wszClassName);
MAKE_UTF8PTR_FROMWIDE(szMethodName, wszMethodName); ADID id;
id.m_dwId=appDomainID;//获取appdomid,通过CreateAppDomainWithManager函数来获取的 ENTER_DOMAIN_ID(id) GCX_PREEMP(); AssemblySpec spec; //实例化一个 AssemblySpec类
spec.Init(szAssemblyName); //用传递过来的程序集名称初始化这类
Assembly* pAsm=spec.LoadAssembly(FILE_ACTIVE);//加载此程序集,返回程序集实例 TypeHandle th=pAsm->GetLoader()->LoadTypeByNameThrowing(pAsm,NULL,szClassName);//获取到程序集的类加载器加载实例TypeHandle 并返回
MethodDesc* pMD=NULL; if (!th.IsTypeDesc())
{
pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Unique);//通过typehandle的方法表以及传递过来的方法名称,获取到方法描述类methoddesc
if (pMD == NULL)
{
// try again without the FM_Unique flag (error path)
pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Default);
if (pMD != NULL)
{
// the method exists but is overloaded
ThrowHR(COR_E_AMBIGUOUSMATCH);
}
}
} if (pMD==NULL || !pMD->IsStatic() || pMD->ContainsGenericVariables())
ThrowHR(COR_E_MISSINGMETHOD); UMEntryThunk *pUMEntryThunk = GetAppDomain()->GetUMEntryThunkCache()->GetUMEntryThunk(pMD);//通过 appdomain 的 getumeentrythunk函数获取到umeentrythunk
*fnPtr = (INT_PTR)pUMEntryThunk->GetCode(); //通过上面获取的 umentrythunk类调用参数getcode ,赋值给传递过来的需要的函数指针参数 END_DOMAIN_TRANSITION; END_EXTERNAL_ENTRYPOINT; END_ENTRYPOINT_NOTHROW; return hr;//标志是否成功
}
Core CLR Host 源码简单分析的更多相关文章
- Django-session中间件源码简单分析
Django-session中间件源码简单分析 settings里有关中间件的配置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddlew ...
- FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg源码简单分析:libswscale的sws_scale()
===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...
- FFmpeg源码简单分析:结构体成员管理系统-AVOption
===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...
- negroni-gzip源码简单分析解读
negroni-gzip源码简单分析解读 这是一个为Negroni设计的gzip压缩处理中间件,需要用到已有的compress中的gzip,阅读了不长的源码之后,总结了一些关键要点和注意点. 检查是否 ...
- FFmpeg的HEVC解码器源码简单分析:概述
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg的HEVC解码器源码简单分析:解码器主干部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- urllib源码简单分析
对下面这段代码做分析 import urllib params = urllib.urlencode({'wd': 'python'}) f = urllib.urlopen("http:/ ...
- CardboardSDK-iOS 源码简单分析
该项目地址: 地址 克隆地址为 https://github.com/rsanchezsaez/CardboardSDK-iOS.git 目前如果想在iOS设备上实现双目VR的功能,Google 已经 ...
随机推荐
- 请使用迭代查找一个list中最小和最大值,并返回一个tuple
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 在Python中,迭代是通过for ... in来完成的,而很多语 ...
- Xmanager 5远程连接CentOS7图形化界面
1.安装Xmanager 5下载链接:https://pan.baidu.com/s/1JwBk3UB4ErIDheivKv4-NA提取码:cw04 双击xmgr5_wm.exe进行安装 点击‘下一步 ...
- python数据库-MySQL查询基本操作(50)
一.条件查询 1.使用where子句对表中的数据筛选,结果为true的行会出现在结果集中 select * from 表名 where 条件; 2.比较运算符 等于= 大于> 大于等于>= ...
- HDU 1394:Minimum Inversion Number(线段树区间求和单点更新)
http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number Problem Description The in ...
- SpringBoot 的过滤器
在Springboot里面读封装的一些常用的API,当然对过滤器也不类外了. 首先讲下Spring中的AOP的理解: AOP不是一种具体的技术,而是一种编程思想.在面向对象编程的过程中,我们很容易通过 ...
- Oracle数据库---存储过程、存储函数
--创建存储过程CREATE OR REPLACE PROCEDURE first_procISBEGIN DBMS_OUTPUT.PUT_LINE('我是过程'); DBMS_OUTPUT.PUT_ ...
- (ps2019)Photoshop 2019 最新破解版下载
Photoshop CC 2019新增功能: 下载地址 点我 新功能介绍:https://helpx.adobe.com/cn/photoshop/using/whats-new.html 经过改良设 ...
- 【POJ - 3050】Hopscotch (dfs+回溯)
-->Hopscotch 这接写中文了 Descriptions: 奶牛们以一种独特的方式玩孩子们的跳房子游戏. 奶牛们创造了一个5x5的格子 他们熟练地跳上其中的一个格子,可以前后左右地跳(不 ...
- 宏旺半导体深度剖析嵌入式存储芯片eMMC原理 一篇概括大全
eMMC 一直是嵌入式存储市场最主流的选择,除了读写速度快.性价比高外,在节省空间方面也是相当优秀,今天宏旺半导体就和大家详细聊聊eMMC. eMMC 是 embedded MultiMediaCar ...
- 以Spring Cache扩展为例介绍如何进行高效的源码的阅读
摘要 日常开发中,需要用到各种各样的框架来实现API.系统的构建.作为程序员,除了会使用框架还必须要了解框架工作的原理.这样可以便于我们排查问题,和自定义的扩展.那么如何去学习框架呢.通常我们通过阅读 ...