在定制 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 源码简单分析的更多相关文章

  1. Django-session中间件源码简单分析

    Django-session中间件源码简单分析 settings里有关中间件的配置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddlew ...

  2. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  3. FFmpeg源码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  4. FFmpeg源码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  5. negroni-gzip源码简单分析解读

    negroni-gzip源码简单分析解读 这是一个为Negroni设计的gzip压缩处理中间件,需要用到已有的compress中的gzip,阅读了不长的源码之后,总结了一些关键要点和注意点. 检查是否 ...

  6. FFmpeg的HEVC解码器源码简单分析:概述

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  7. FFmpeg的HEVC解码器源码简单分析:解码器主干部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  8. urllib源码简单分析

    对下面这段代码做分析 import urllib params = urllib.urlencode({'wd': 'python'}) f = urllib.urlopen("http:/ ...

  9. CardboardSDK-iOS 源码简单分析

    该项目地址: 地址 克隆地址为 https://github.com/rsanchezsaez/CardboardSDK-iOS.git 目前如果想在iOS设备上实现双目VR的功能,Google 已经 ...

随机推荐

  1. Storm 学习之路(二)—— Storm核心概念详解

    一.Storm核心概念 1.1 Topologies(拓扑) 一个完整的Storm流处理程序被称为Storm topology(拓扑).它是一个是由Spouts 和Bolts通过Stream连接起来的 ...

  2. java写出PDF

    1\包 <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</ar ...

  3. Ubuntu 16.04.3启动MySQL报错

    今天安装mysql,连接MySQL时报错mysql: [Warning] Using a password on the command line interface can be insecure. ...

  4. redhat6.0下配置DNS

    最近操作系统要结课,老师要求在redhat上配置各种服务器角色,包括dhcp.ftp.web.dns.前三个都还好,但就dns,被折磨的死去活来的,真让人头大.还好在同学的帮助下最后配置成功,实现了正 ...

  5. HDU 1025:Constructing Roads In JGShining's Kingdom(LIS+二分优化)

    http://acm.hdu.edu.cn/showproblem.php?pid=1025 Constructing Roads In JGShining's Kingdom Problem Des ...

  6. BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 题意:简单明了. 思路:终于好像有点明白CDQ分治处理三维偏序了.把删除操作看作是插入操作,那 ...

  7. 解决 Prometheus 不能获取 Kubernetes 集群上 Windows 节点的 Metrics

    背景 接上一篇 快速搭建 Windows Kubernetes , 我们发现原来在 Windows Kubernetes 会有一些与在 Linux 上使用不一样的体验,俗称坑,例如 hostAlias ...

  8. python generator与coroutine

    python  generator与coroutine 协程 简单介绍 协程,又称微线程,纤程,英文名Coroutine.协程是一种用户态的轻量级线程,又称微线程.协程拥有自己的寄存器上下文和栈,调度 ...

  9. ansible安装应用软件

    1.创建相应的目录: mkdir -p /ansible/roles/{nginx,mysql,tomcat,db,zabbix}/{defaults,files,handlers,meta,task ...

  10. 七牛云图床和Markdown使用

    七牛云图床和Markdown使用 1.图床是什么? 图床一般是指储存图片的服务器,有国内和国外之分.国外的图床由于有空间距离等因素决定访问速度很慢影响图片显示速度.国内也分为单线空间.多线空间和cdn ...