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 已经 ...
随机推荐
- spring cloud 系列第4篇 —— feign 声明式服务调用 (F版本)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.feign 简介 在上一个用例中,我们使用ribbon+restTem ...
- swoole异步任务数据报表生成
<?php include 'vendor/autoload.php'; class server { private $serv; private $db; /** * [__construc ...
- 面试中的作用域题和THIS 指向的问题
作用域的面试题 1. fn() function fn () { console.log(12) } var as = function () { console.log(45) } 2. var a ...
- SQLPLUS执行PL/SQL语句块
1.首先登录Oracle HR schema: 2.对于PL/SQL程序,分号表示语句的结束:而使用 "." 号表示整个语句块的结束,也可以省略.按回车键后,该语句块不会执行,即 ...
- pytorch实现yolov3(4) 非极大值抑制nms
在上一篇里我们实现了forward函数.得到了prediction.此时预测出了特别多的box以及各种class probability,现在我们要从中过滤出我们最终的预测box. 理解了yolov3 ...
- C++ hdu 例题:不要62 题解
例题:不要62 同步数位DP 需要统计区间[l,r]的满足题意的数的个数,这往往可以转换成求[0,r]-[0,l) 基本思想与方法 有了上述性质,我们就可以从高到低枚举第一次<n对应位是哪一位. ...
- 每天学点node系列-fs文件系统
好的代码像粥一样,都是用时间熬出来的. 概述 文件 I/O 是由简单封装的标准 POSIX 函数提供的. 通过 require('fs') 使用该模块. 所有文件系统操作都具有同步和异步的形式. 异步 ...
- leadcode的Hot100系列--78. 子集--位运算
看一个数组的子集有多少,其实就是排列组合, 比如:[0,1] 对应的子集有:[] [0] [1] [1,1] 这四种. 一般对应有两种方法:位运算 和 回溯. 这里先使用位运算来做. 位运算 一个长度 ...
- POJ 1113:Wall(凸包)
http://poj.org/problem?id=1113 Wall Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 346 ...
- Oracle数据库---PLSQL
SET SERVEROUTPUT ONBEGIN --打印输出 DBMS_OUTPUT.PUT_LINE('hello everyone!');END; DECLARE v_name VARCHAR2 ...