static const char * const coreClrDll = "libcoreclr.so";
#endif
-// Windows types used by the ExecuteAssembly function
-typedef unsigned int DWORD;
-typedef const char16_t* LPCWSTR;
-typedef const char* LPCSTR;
-typedef int32_t HRESULT;
-
-#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
-
-// Prototype of the ExecuteAssembly function from the libcoreclr.do
-typedef HRESULT (*ExecuteAssemblyFunction)(
- LPCSTR exePath,
- LPCSTR coreClrPath,
- LPCSTR appDomainFriendlyName,
- int propertyCount,
- LPCSTR* propertyKeys,
- LPCSTR* propertyValues,
- int argc,
- LPCSTR* argv,
- LPCSTR managedAssemblyPath,
- LPCSTR entryPointAssemblyName,
- LPCSTR entryPointTypeName,
- LPCSTR entryPointMethodsName,
- DWORD* exitCode);
+#define SUCCEEDED(Status) ((Status) >= 0)
+
+// Prototype of the coreclr_initialize function from the libcoreclr.so
+typedef int (*InitializeCoreCLRFunction)(
+ const char* exePath,
+ const char* appDomainFriendlyName,
+ int propertyCount,
+ const char** propertyKeys,
+ const char** propertyValues,
+ void** hostHandle,
+ unsigned int* domainId);
+
+// Prototype of the coreclr_shutdown function from the libcoreclr.so
+typedef int (*ShutdownCoreCLRFunction)(
+ void* hostHandle,
+ unsigned int domainId);
+
+// Prototype of the coreclr_execute_assembly function from the libcoreclr.so
+typedef int (*ExecuteAssemblyFunction)(
+ void* hostHandle,
+ unsigned int domainId,
+ int argc,
+ const char** argv,
+ const char* managedAssemblyPath,
+ unsigned int* exitCode);
bool GetAbsolutePath(const char* path, std::string& absolutePath)
{
void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL);
if (coreclrLib != nullptr)
{
- ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "ExecuteAssembly");
- if (executeAssembly != nullptr)
+ InitializeCoreCLRFunction initializeCoreCLR = (InitializeCoreCLRFunction)dlsym(coreclrLib, "coreclr_initialize");
+ ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "coreclr_execute_assembly");
+ ShutdownCoreCLRFunction shutdownCoreCLR = (ShutdownCoreCLRFunction)dlsym(coreclrLib, "coreclr_shutdown");
+
+ if (initializeCoreCLR == nullptr)
+ {
+ fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n");
+ }
+ else if (executeAssembly == nullptr)
+ {
+ fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n");
+ }
+ else if (shutdownCoreCLR == nullptr)
+ {
+ fprintf(stderr, "Function coreclr_shutdown not found in the libcoreclr.so\n");
+ }
+ else
{
// Allowed property names:
// APPBASE
"UseLatestBehaviorWhenTFMNotSpecified"
};
- HRESULT st = executeAssembly(
- currentExeAbsolutePath,
- coreClrDllPath.c_str(),
- "unixcorerun",
- sizeof(propertyKeys) / sizeof(propertyKeys[0]),
- propertyKeys,
- propertyValues,
- managedAssemblyArgc,
- managedAssemblyArgv,
- managedAssemblyAbsolutePath,
- NULL,
- NULL,
- NULL,
- (DWORD*)&exitCode);
+ void* hostHandle;
+ unsigned int domainId;
+
+ int st = initializeCoreCLR(
+ currentExeAbsolutePath,
+ "unixcorerun",
+ sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+ propertyKeys,
+ propertyValues,
+ &hostHandle,
+ &domainId);
if (!SUCCEEDED(st))
{
- fprintf(stderr, "ExecuteAssembly failed - status: 0x%08x\n", st);
+ fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st);
exitCode = -1;
}
- }
- else
- {
- fprintf(stderr, "Function ExecuteAssembly not found in the libcoreclr.so\n");
+ else
+ {
+ st = executeAssembly(
+ hostHandle,
+ domainId,
+ managedAssemblyArgc,
+ managedAssemblyArgv,
+ managedAssemblyAbsolutePath,
+ (unsigned int*)&exitCode);
+
+ if (!SUCCEEDED(st))
+ {
+ fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st);
+ exitCode = -1;
+ }
+
+ st = shutdownCoreCLR(hostHandle, domainId);
+ if (!SUCCEEDED(st))
+ {
+ fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st);
+ exitCode = -1;
+ }
+ }
}
if (dlclose(coreclrLib) != 0)
}
//
-// Execute a managed assembly with given arguments
+// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
//
// Parameters:
// exePath - Absolute path of the executable that invoked the ExecuteAssembly
-// coreClrPath - Absolute path of the libcoreclr.so
// appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
// propertyCount - Number of properties (elements of the following two arguments)
// propertyKeys - Keys of properties of the app domain
// propertyValues - Values of properties of the app domain
-// argc - Number of arguments passed to the executed assembly
-// argv - Array of arguments passed to the executed assembly
-// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
-// enntyPointAssemblyName - Name of the assembly which holds the custom entry point (or NULL to use managedAssemblyPath).
-// entryPointTypeName - Name of the type which holds the custom entry point (or NULL to use managedAssemblyPath).
-// entryPointMethodName - Name of the method which is the custom entry point (or NULL to use managedAssemblyPath).
-// exitCode - Exit code returned by the executed assembly
+// hostHandle - Output parameter, handle of the created host
+// domainId - Output parameter, id of the created app domain
//
// Returns:
// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
-HRESULT ExecuteAssembly(
- LPCSTR exePath,
- LPCSTR coreClrPath,
- LPCSTR appDomainFriendlyName,
+int coreclr_initialize(
+ const char* exePath,
+ const char* appDomainFriendlyName,
int propertyCount,
- LPCSTR* propertyKeys,
- LPCSTR* propertyValues,
- int argc,
- LPCSTR* argv,
- LPCSTR managedAssemblyPath,
- LPCSTR entryPointAssemblyName,
- LPCSTR entryPointTypeName,
- LPCSTR entryPointMethodName,
- DWORD* exitCode)
+ const char** propertyKeys,
+ const char** propertyValues,
+ void** hostHandle,
+ unsigned int* domainId)
{
- if (exitCode == NULL)
- {
- return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
- }
- *exitCode = -1;
-
DWORD error = PAL_InitializeCoreCLR(exePath);
HRESULT hr = HRESULT_FROM_WIN32(error);
ConstWStringArrayHolder propertyValuesW;
propertyValuesW.Set(StringArrayToUnicode(propertyCount, propertyValues), propertyCount);
- DWORD domainId;
-
hr = host->CreateAppDomainWithManager(
appDomainFriendlyNameW,
// Flags:
propertyCount,
propertyKeysW,
propertyValuesW,
- &domainId);
+ domainId);
+
+ if (SUCCEEDED(hr))
+ {
+ host.SuppressRelease();
+ *hostHandle = host;
+ }
+
+ return hr;
+}
+
+//
+// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
+//
+// Parameters:
+// hostHandle - Handle of the host
+// domainId - Id of the domain
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+int coreclr_shutdown(
+ void* hostHandle,
+ unsigned int domainId)
+{
+ ReleaseHolder<ICLRRuntimeHost2> host(reinterpret_cast<ICLRRuntimeHost2*>(hostHandle));
+ HRESULT hr = host->UnloadAppDomain(domainId,
+ true); // Wait until done
+ IfFailRet(hr);
+
+ hr = host->Stop();
+
+ // The PAL_Terminate is not called here since it would terminate the current process.
+
+ return hr;
+}
+
+//
+// Create a native callable delegate for a managed method.
+//
+// Parameters:
+// hostHandle - Handle of the host
+// domainId - Id of the domain
+// entryPointAssemblyName - Name of the assembly which holds the custom entry point
+// entryPointTypeName - Name of the type which holds the custom entry point
+// entryPointMethodName - Name of the method which is the custom entry point
+// delegate - Output parameter, the function stores a pointer to the delegate at the specified address
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+int coreclr_create_delegate(
+ void* hostHandle,
+ unsigned int domainId,
+ const char* entryPointAssemblyName,
+ const char* entryPointTypeName,
+ const char* entryPointMethodName,
+ void** delegate)
+{
+ ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);
+
+ ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName);
+ ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName);
+ ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName);
+
+ HRESULT hr = host->CreateDelegate(
+ domainId,
+ entryPointAssemblyNameW,
+ entryPointTypeNameW,
+ entryPointMethodNameW,
+ (INT_PTR*)delegate);
+
+ return hr;
+}
+
+//
+// Execute a managed assembly with given arguments
+//
+// Parameters:
+// hostHandle - Handle of the host
+// domainId - Id of the domain
+// argc - Number of arguments passed to the executed assembly
+// argv - Array of arguments passed to the executed assembly
+// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
+// exitCode - Exit code returned by the executed assembly
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+int coreclr_execute_assembly(
+ void* hostHandle,
+ unsigned int domainId,
+ int argc,
+ const char** argv,
+ const char* managedAssemblyPath,
+ unsigned int* exitCode)
+{
+ if (exitCode == NULL)
+ {
+ return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ }
+ *exitCode = -1;
+
+ ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);
+
+ ConstWStringArrayHolder argvW;
+ argvW.Set(StringArrayToUnicode(argc, argv), argc);
+
+ ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath);
+
+ HRESULT hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, exitCode);
+ IfFailRet(hr);
+
+ return hr;
+}
+
+//
+// Execute a managed assembly with given arguments
+//
+// Parameters:
+// exePath - Absolute path of the executable that invoked the ExecuteAssembly
+// coreClrPath - Absolute path of the libcoreclr.so
+// appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
+// propertyCount - Number of properties (elements of the following two arguments)
+// propertyKeys - Keys of properties of the app domain
+// propertyValues - Values of properties of the app domain
+// argc - Number of arguments passed to the executed assembly
+// argv - Array of arguments passed to the executed assembly
+// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
+// enntyPointAssemblyName - Name of the assembly which holds the custom entry point (or NULL to use managedAssemblyPath).
+// entryPointTypeName - Name of the type which holds the custom entry point (or NULL to use managedAssemblyPath).
+// entryPointMethodName - Name of the method which is the custom entry point (or NULL to use managedAssemblyPath).
+// exitCode - Exit code returned by the executed assembly
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+HRESULT ExecuteAssembly(
+ LPCSTR exePath,
+ LPCSTR coreClrPath,
+ LPCSTR appDomainFriendlyName,
+ int propertyCount,
+ LPCSTR* propertyKeys,
+ LPCSTR* propertyValues,
+ int argc,
+ LPCSTR* argv,
+ LPCSTR managedAssemblyPath,
+ LPCSTR entryPointAssemblyName,
+ LPCSTR entryPointTypeName,
+ LPCSTR entryPointMethodName,
+ DWORD* exitCode)
+{
+ if (exitCode == NULL)
+ {
+ return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ }
+ *exitCode = -1;
+
+ ReleaseHolder<ICLRRuntimeHost2> host; //(reinterpret_cast<ICLRRuntimeHost2*>(hostHandle));
+ DWORD domainId;
+
+ HRESULT hr = coreclr_initialize(exePath, appDomainFriendlyName, propertyCount, propertyKeys, propertyValues, &host, &domainId);
IfFailRet(hr);
ConstWStringArrayHolder argvW;
*exitCode = pHostMain(argc, argvW);
}
-
- hr = host->UnloadAppDomain(domainId,
- true); // Wait until done
- IfFailRet(hr);
-
- hr = host->Stop();
- // The PAL_Terminate is not called here since it would terminate the current process.
+ hr = coreclr_shutdown(host, domainId);
return hr;
}