CoreCLR Host源码分析(C++)
Posted tangyanzhi1111
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; //返回程序集 }
以上是关于CoreCLR Host源码分析(C++)的主要内容,如果未能解决你的问题,请参考以下文章