14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/String.h"
16#include "arcane/utils/CommandLineArguments.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/Exception.h"
19#include "arcane/utils/CheckedConvert.h"
20#include "arcane/core/Directory.h"
35#include <coreclr_delegates.h>
40using string_t = std::basic_string<char_t>;
58 char_t* _duplicate(
const char_t* x)
64 std::wstring_view wstr_view(x);
78#define MAX_PATH PATH_MAX
86 char_t* _duplicate(
const char_t* x)
106int dotnet_verbose = 0;
109using LibHandle = HMODULE;
111using LibHandle =
void*;
120 LibHandle m_lib_handle = (LibHandle)0;
121 bool m_has_valid_lib_handle =
false;
123 hostfxr_initialize_for_runtime_config_fn init_fptr =
nullptr;
124 hostfxr_initialize_for_dotnet_command_line_fn init_command_line_fptr =
nullptr;
125 hostfxr_get_runtime_delegate_fn get_delegate_fptr =
nullptr;
126 hostfxr_run_app_fn run_app_fptr =
nullptr;
127 hostfxr_close_fn close_fptr =
nullptr;
134#define PRINT_FORMAT(level,str,...) \
135 if (dotnet_verbose>=level)\
136 std::cout << String::format("[coreclr] " str "\n",__VA_ARGS__);
140#if defined(ARCANE_DOTNET_ROOT)
141const char* arcane_dotnet_root = ARCANE_DOTNET_ROOT;
143const char* arcane_dotnet_root =
nullptr;
148std::string arcane_dotnet_root_env_variable;
153bool load_hostfxr(
const string_t& assembly_name);
157load_assembly_and_get_function_pointer_fn
158getDotnetLoadAssembly(
const String& assembly)
160 string_t assembly1 = _toString(assembly);
162 void* load_assembly_and_get_function_pointer =
nullptr;
163 hostfxr_handle cxt =
nullptr;
165 hostfxr_initialize_parameters params;
166 params.size =
sizeof(params);
168 params.host_path = assembly1.c_str();
170 int rc = lib_info.init_fptr(assembly1.c_str(), ¶ms, &cxt);
171 if (rc != 0 || cxt ==
nullptr) {
172 auto flags = std::cerr.flags();
173 std::cerr <<
"Init failed: " << std::hex << std::showbase << rc << std::endl;
174 std::cerr.setf(flags);
175 lib_info.close_fptr(cxt);
180 rc = lib_info.get_delegate_fptr(cxt, hdt_load_assembly_and_get_function_pointer,
181 &load_assembly_and_get_function_pointer);
182 if (rc != 0 || load_assembly_and_get_function_pointer ==
nullptr)
183 std::cerr <<
"Get delegate failed: " << std::hex << std::showbase << rc << std::endl;
185 lib_info.close_fptr(cxt);
186 return (load_assembly_and_get_function_pointer_fn)load_assembly_and_get_function_pointer;
195 const String& orig_assembly_name)
197 using const_char_t =
const char_t*;
199 int argc = *(cmd_args.commandLineArgc());
203 string_t root_path1 = _toString(root_path);
204 string_t orig_assembly_name1 = _toString(orig_assembly_name);
205 std::cerr <<
"ENTERING _execDirect root_path=" << root_path <<
"\n";
207 string_t dotnet_root = _toString(
String(arcane_dotnet_root));
208 hostfxr_initialize_parameters params;
209 params.size =
sizeof(params);
210 params.host_path = root_path1.c_str();
211#ifdef ARCANE_OS_WIN32
216 params.dotnet_root =
nullptr;
218 params.dotnet_root = dotnet_root.c_str();
220 const_char_t* argv =
new const_char_t[1];
221 char_t* argv0_str = _duplicate((
const char_t*)(orig_assembly_name1.c_str()));
223 std::cerr <<
"_execDirect argv[0] =" << orig_assembly_name <<
"\n";
226 hostfxr_handle host_context_handle;
227 int rc = lib_info.init_command_line_fptr(argc, (
const char_t**)argv, ¶ms, &host_context_handle);
228 std::cerr <<
"_execDirect init_command_line R = " << rc <<
"\n";
233 size_t buffer_used = 0;
234 if (hostfxr_get_runtime_property(host_context_handle,
"TEST_PROPERTY",
nullptr, 0, &buffer_used) == HostApiMissingProperty) {
235 hostfxr_set_runtime_property(host_context_handle,
"TEST_PROPERTY",
"TRUE");
239 std::cerr <<
"Launching '.Net'\n";
240 int r = lib_info.run_app_fptr(host_context_handle);
241 std::cerr <<
"End '.Net': R=" << r <<
"\n";
244 lib_info.close_fptr(host_context_handle);
260 if (!verbose_str.
null())
268 if (!dotnet_root_env.
null()){
270 arcane_dotnet_root = arcane_dotnet_root_env_variable.c_str();
274 PRINT_FORMAT(1,
"ARCANE_DOTNET_CORECLR_MAIN assembly_name={0}",orig_assembly_name);
276 if (orig_assembly_name.
empty())
279 string_t orig_assembly_name1 = _toString(orig_assembly_name);
283 PRINT_FORMAT(1,
"ENTERING CORECLR_MAIN root_path={0}",root_path);
288 if (!load_hostfxr(orig_assembly_name1))
291 const bool do_direct_exec =
true;
293 return _execDirect(cmd_args, orig_assembly_name);
301 load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer =
nullptr;
302 load_assembly_and_get_function_pointer = getDotnetLoadAssembly(config_path);
303 assert(load_assembly_and_get_function_pointer !=
nullptr &&
"Failure: get_dotnet_load_assembly()");
309 const char_t* dotnet_type = STR(
"ArcaneMainExec, Arcane.Main");
310 const char_t* dotnet_type_method = STR(
"CoreClrComponentEntryPoint");
313 component_entry_point_fn dll_entry_point_func =
nullptr;
316 int rc = load_assembly_and_get_function_pointer(orig_assembly_name1.c_str(),
321 (
void**)&dll_entry_point_func);
324 ARCANE_FATAL(
"load_assembly_and_get_function_pointer: rc={0}", rc);
325 if (!dll_entry_point_func)
326 ARCANE_FATAL(
"Failure: load_assembly_and_get_function_pointer()");
333 const char_t* message;
336 lib_args args{ STR(
"from host!"), 0 };
338 return dll_entry_point_func(&args,
sizeof(args));
345extern "C" ARCANE_EXPORT
int
351 ret = _arcaneCoreClrMainInternal(cmd_args,orig_assembly_name);
354 ret = arcanePrintArcaneException(ex,
nullptr);
356 catch(
const std::exception& ex){
357 ret = arcanePrintStdException(ex,
nullptr);
360 ret = arcanePrintAnyException(
nullptr);
376LibHandle load_library(
const char_t*);
377void* get_export(LibHandle,
const char*);
380LibHandle load_library(
const char_t* path)
382 HMODULE h = ::LoadLibraryW(path);
384 ARCANE_FATAL(
"Can not load library '{0}'",_toArcaneString(path));
387void free_library(LibHandle h)
391void* get_export(LibHandle h,
const char* name)
393 void* f = ::GetProcAddress(h, name);
399LibHandle load_library(
const char_t* path)
401 void* h = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
403 ARCANE_FATAL(
"Can not load library '{0}' error='{1}'",path,dlerror());
406void free_library(LibHandle h)
410void* get_export(LibHandle h,
const char* name)
412 void* f = dlsym(h, name);
413 PRINT_FORMAT(1,
"get_export name={0} f={1}",name,f);
415 PRINT_FORMAT(0,
"Can not get library symbol '{0}' error='{1}'",name,dlerror());
423load_hostfxr(
const string_t& assembly_name)
429 string_t dotnet_root = _toString(
String(arcane_dotnet_root));
430 get_hostfxr_parameters hostfxr_parameters;
431 hostfxr_parameters.size =
sizeof(get_hostfxr_parameters);
432 hostfxr_parameters.assembly_path = assembly_name.c_str();
433 hostfxr_parameters.dotnet_root = dotnet_root.c_str();
435 PRINT_FORMAT(1,
"Entering load_hostfxr() dotnet_root={0}",arcane_dotnet_root);
437 const int BUF_LEN = 12000;
438 char_t buffer[BUF_LEN];
439 size_t buffer_size =
sizeof(buffer) /
sizeof(char_t);
446 int rc = get_hostfxr_path(buffer, &buffer_size, &hostfxr_parameters);
447 PRINT_FORMAT(1,
"Return value of 'get_hostfxr_path' = '{0}'",rc);
449 PRINT_FORMAT(0,
"Error or warning calling 'get_hostfxr_path' = '{0}'",rc);
454 LibHandle lib = load_library(buffer);
455 PRINT_FORMAT(1,
"LIB_PTR={0} path={1}",lib,_toArcaneString(buffer));
456 lib_info.m_lib_handle = lib;
457 lib_info.m_has_valid_lib_handle =
true;
458 lib_info.init_fptr = (hostfxr_initialize_for_runtime_config_fn)get_export(lib,
"hostfxr_initialize_for_runtime_config");
459 lib_info.get_delegate_fptr = (hostfxr_get_runtime_delegate_fn)get_export(lib,
"hostfxr_get_runtime_delegate");
460 lib_info.close_fptr = (hostfxr_close_fn)get_export(lib,
"hostfxr_close");
461 lib_info.init_command_line_fptr = (hostfxr_initialize_for_dotnet_command_line_fn)get_export(lib,
"hostfxr_initialize_for_dotnet_command_line");
462 lib_info.run_app_fptr = (hostfxr_run_app_fn)get_export(lib,
"hostfxr_run_app");
463 return (lib_info.init_fptr && lib_info.get_delegate_fptr && lib_info.close_fptr && lib_info.init_command_line_fptr && lib_info.run_app_fptr);
474 if (m_has_valid_lib_handle){
475 free_library(m_lib_handle);
476 m_lib_handle = (LibHandle)0;
478 m_has_valid_lib_handle =
false;
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur les chaînes de caractères.
ARCCORE_BASE_EXPORT std::wstring convertToStdWString(const String &str)
Retourne la conversion de str en std::wstring.
ARCCORE_BASE_EXPORT String convertToArcaneString(const std::wstring_view &wstr)
Convertie wstr en une String.
Arguments de la ligne de commande.
Classe gérant un répertoire.
String file(const String &file_name) const override
Retourne le chemin complet du fichier file_name dans le répertoire.
Classe de base d'une exception.
Vue sur une chaîne de caractères UTF-8.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
bool empty() const
Vrai si la chaîne est vide (nulle ou "")
std::string_view toStdStringView() const
Retourne une vue de la STL sur la chaîne actuelle.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-