zoukankan      html  css  js  c++  java
  • CoreCLR Host源码分析(C++)

      废话不多说,直接上源码:

    1.在托管程序集里面执行方法

    
    
    HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId,//通过CreateAppDomainWithManager创造的domainid
                                          LPCWSTR pwzAssemblyPath,//要托管的.net core DLL 路径
                                          int argc, //传递进来参数个数
                                          LPCWSTR* argv,//传递进来参数数组
                                          DWORD *pReturnValue)//指示函数执行的结果标记
    {
        CONTRACTL
        {
            THROWS; // Throws...as we do not want it to swallow the managed exception
            ENTRY_POINT;
        }
        CONTRACTL_END;
    
        // This is currently supported in default domain only
        if (dwAppDomainId != DefaultADID) //如果不等于默认defaultADID 直接返回失败标记
            return HOST_E_INVALIDOPERATION;
    
        // No point going further if the runtime is not running...
        if (!IsRuntimeActive() || !m_fStarted) //如果 coreclr host 没有在运行或者m_fstarted标记没有被启动,返回失败标记
        {
            return HOST_E_CLRNOTAVAILABLE;
        }   
       
        if(!pwzAssemblyPath) //如果托管的DLL为空,返回
            return E_POINTER;
    
        if(argc < 0)//如果参数个数小于零,返回
        {
            return E_INVALIDARG;
        }
    
        if(argc > 0 && argv == NULL)//如果参数个数大于零且参数数组等于零,返回
        {
            return E_INVALIDARG;
        }
    
        HRESULT hr = S_OK; //初始化hr
    
        AppDomain *pCurDomain = SystemDomain::GetCurrentDomain(); //获取到当前appdomain的实例
    
        Thread *pThread = GetThread(); //获取到当前进程指针
        if (pThread == NULL) //如果进程指针为零
        {
            pThread = SetupThreadNoThrow(&hr);
            if (pThread == NULL)
            {
                goto ErrExit;
            }
        }
    
        if(pCurDomain->GetId().m_dwId != DefaultADID)//如果当前进程的ID不等于defaultadid返回
        {
            return HOST_E_INVALIDOPERATION;
        }
    
        INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
        INSTALL_UNWIND_AND_CONTINUE_HANDLER;
    
        _ASSERTE (!pThread->PreemptiveGCDisabled());
    
        Assembly *pAssembly = AssemblySpec::LoadAssembly(pwzAssemblyPath); //加载传递过来的托管程序集,并且实例化
    
    #if defined(FEATURE_MULTICOREJIT)
        pCurDomain->GetMulticoreJitManager().AutoStartProfile(pCurDomain);
    #endif // defined(FEATURE_MULTICOREJIT)
    
        {
            GCX_COOP();
    
            // Here we call the managed method that gets the cmdLineArgs array.
            SetCommandLineArgs(pwzAssemblyPath, argc, argv);//设置命令行参数
    
            PTRARRAYREF arguments = NULL;
            GCPROTECT_BEGIN(arguments);
    
            arguments = (PTRARRAYREF)AllocateObjectArray(argc, g_pStringClass);//分配内存
            for (int i = 0; i < argc; ++i)
            {
                STRINGREF argument = StringObject::NewString(argv[i]);//转换参数
                arguments->SetAt(i, argument);//设置参数数组标记
            }
    
            DWORD retval = pAssembly->ExecuteMainMethod(&arguments, TRUE /*waitForOtherThreads */); //执行需要托管的method
            if (pReturnValue) //如果返回标记不为空
            {
                *pReturnValue = retval;//赋值
            }
    
            GCPROTECT_END();
    
        }
    
        UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
        UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    
    ErrExit: //如果错误,调到errexit ,返回HR
    
        return hr;
    }
    
    
    

      

    2.利用非托管加载程序集

    Assembly *AssemblySpec::LoadAssembly(LPCWSTR pFilePath) // 传递托管程序集路径
    {
        CONTRACT(Assembly *)
        {
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
            PRECONDITION(CheckPointer(pFilePath));
            POSTCONDITION(CheckPointer(RETVAL));
            INJECT_FAULT(COMPlusThrowOM(););
        }
        CONTRACT_END;
    
        AssemblySpec spec; //初始化assemblyspec 类
        spec.SetCodeBase(pFilePath); //设置类的托管程序集路径
        RETURN spec.LoadAssembly(FILE_LOADED); //设置类的加载方式为 文件加载
    }
    
    DomainAssembly *AssemblySpec::LoadDomainAssembly(FileLoadLevel targetLevel, //加载方式,为文件加载,另外三个参数都为空
                                                     BOOL fThrowOnFileNotFound,
                                                     BOOL fRaisePrebindEvents,
                                                     StackCrawlMark *pCallerStackMark)
    {
        CONTRACT(DomainAssembly *)
        {
            INSTANCE_CHECK;
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
            POSTCONDITION((!fThrowOnFileNotFound && CheckPointer(RETVAL, NULL_OK))
                          || CheckPointer(RETVAL));
            INJECT_FAULT(COMPlusThrowOM(););
        }
        CONTRACT_END;
     
        ETWOnStartup (LoaderCatchCall_V1, LoaderCatchCallEnd_V1); //初始化一些宏定义
        AppDomain* pDomain = GetAppDomain(); //获取当前 appdomain 的实例
    
    
        DomainAssembly *pAssembly = nullptr; //声明并赋值一个 domainassembly
    
        ICLRPrivBinder * pBinder = GetHostBinder(); //获取到 iclrprivbinder 对象
        
        // If no binder was explicitly set, check if parent assembly has a binder.
        if (pBinder == nullptr) //如果 pbinder等于零
        {
            pBinder = GetBindingContextFromParentAssembly(pDomain); //获取到父类和注入的一些方法
        }
    
    
        if (pBinder != nullptr)//如果获取到了
        {
            ReleaseHolder<ICLRPrivAssembly> pPrivAssembly;
            HRESULT hrCachedResult;
            if (SUCCEEDED(pBinder->FindAssemblyBySpec(GetAppDomain(), this, &hrCachedResult, &pPrivAssembly)) &&
                SUCCEEDED(hrCachedResult))//用pbinder找到appdomain 的pprivassembly
            {
                pAssembly = pDomain->FindAssembly(pPrivAssembly);//利用找到的pprivassembly,pdomain调用然后赋值给要返回的程序集
            }
        }
    
        if ((pAssembly == nullptr) && CanUseWithBindingCache()) //如果为空
        {
            pAssembly = pDomain->FindCachedAssembly(this);//pdomain带上当前类的实例去缓存里面找当前的程序集
        }
    
        if (pAssembly)//如果找到
        {
            pDomain->LoadDomainFile(pAssembly, targetLevel); //以文件方式加载程序集
            RETURN pAssembly; //然后返回
        }
    
    
        PEAssemblyHolder pFile(pDomain->BindAssemblySpec(this, fThrowOnFileNotFound, fRaisePrebindEvents, pCallerStackMark));//如果上面所有步骤都不行,实例化一个peassemblyholder,
        if (pFile == NULL)
            RETURN NULL;
    
        pAssembly = pDomain->LoadDomainAssembly(this, pFile, targetLevel);//利用这个实例化的peassemblyholder和this指针,以及文件加载的方式去获取程序集
    
        RETURN pAssembly; //返回程序集
    }
  • 相关阅读:
    大型网站调试工具之一(php性能优化分析工具XDebug)
    2.0控件之Border, Button, Calendar, Canvas, CheckBox, ComboBox
    C#程序开发范例_IC卡读写
    数据库连接池技术
    控件之DataGrid, DatePicker, Grid, GridSplitter, HyperlinkButton, Image
    软件工程师职业总结
    "EMQ Meetup北京"技术沙龙分享会
    EMQ X Enterprise 新功能 Rule Engine 介绍
    基于 MySQL 的 EMQ X Auth & ACL
    MQTT 5.0 新特性(三)— 有效载荷标识与内容类型
  • 原文地址:https://www.cnblogs.com/tangyanzhi1111/p/10616058.html
Copyright © 2011-2022 走看看