zoukankan      html  css  js  c++  java
  • 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;//标志是否成功
    }
  • 相关阅读:
    [快捷键的使用] IntelliJ IDEA 将数据库里面的表转化为对象
    Mybatis事物浅谈
    CentOS7系统局域网内配置本地yum源解决cannot find a valid baseurl for repo
    CentOS6.5系统解决中文乱码问题
    tomcat启动报错:Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
    zabbix3.4.8中提示host [4gronghe_110] not found
    CentOS7.6系统安装详解(含真机装系统的采坑之旅)!
    windows server 2012 R2修改默认远程端口
    两个div并排,右边div固定宽度,左边宽度自适应
    两个div并排,左边div固定宽度,右边宽度自适应
  • 原文地址:https://www.cnblogs.com/tangyanzhi1111/p/10594812.html
Copyright © 2011-2022 走看看