在定制 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. ssm中mapper注入失败的传奇经历

    最近因为要测试一个功能,需要用最短的时间来启动服务,开启测试程序,但平常所用的框架中已经集成了各种三方的东西,想着那就再重新搭建一个最简单的ssm框架吧. 搭建可参考:简单ssm最新搭建 搭建过程并不 ...

  2. 简单DI

    <?php class DI { private $container; public function set($key, $obj, ...$args) { $this->contai ...

  3. CentOS下查看机器配置

    1.查看系统位数.内核版本 [root@localhost ~]# uname -a Linux localhost.localdomain 3.10.0-693.11.6.el7.x86_64 #1 ...

  4. [apue] 等待子进程的那些事儿

    谈到等待子进程,首先想到的就是SIGCHLD信号与wait函数族,本文试图厘清二者的方方面面,以及组合使用时可能不小心掉进去的坑. 1. 首先谈单独使用SIGCHLD的场景.下面是一段典型的代码片段: ...

  5. vboxnetctl: no such file or directory

     sudo /Library/StartupItems/VirtualBox/VirtualBox restart sudo /Library/StartupItems/VirtualBox/Vir ...

  6. ORACLE常用函数的使用方法

    ORACLE常用函数的使用方法 1. 字符串函数 (1) length(); 获取字符长度SELECT LENGTH('中国') FROM PLATFORM_METAINFO_TABLES WHERE ...

  7. navicat中查重并删除

    # 查询所有重复的数据 SELECT * FROM hao123 WHERE ir_url IN (SELECT ir_url FROM `hao123` GROUP BY ir_url having ...

  8. Spring Cloud Alibaba | Nacos配置管理

    目录 Spring Cloud Alibaba | Nacos配置管理 1. pom.xml 项目依赖 2. 在 bootstrap.properties 中配置 Nacos server 的地址和应 ...

  9. 成功解决 org.mybatis.spring.MyBatisSystemException问题!!

    org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingExce ...

  10. 牛逼了,教你用九种语言在JVM上输出HelloWorld

    我们在<深入分析Java的编译原理>中提到过,为了让Java语言具有良好的跨平台能力,Java独具匠心的提供了一种可以在所有平台上都能使用的一种中间代码——字节码(ByteCode). 有 ...