From bf16880cebb3f119dc2a14cb00947be7732e705c Mon Sep 17 00:00:00 2001 From: Ian Peter Du Date: Mon, 4 Mar 2024 12:32:17 +0100 Subject: [PATCH 1/5] Fixes #31 rSharp_create_domain need an argument for library location (#31) --- src/rSharp.cpp | 26 ++++++++++++++++++++++---- src/rSharp.h | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/rSharp.cpp b/src/rSharp.cpp index f114b77..d914be6 100644 --- a/src/rSharp.cpp +++ b/src/rSharp.cpp @@ -36,8 +36,8 @@ void freeObject(RSharpGenericValue* instance); ///////////////////////////////////////// // Initialization and disposal of the CLR ///////////////////////////////////////// -void rSharp_create_domain() { - +void rSharp_create_domain(char ** libPath) +{ // if already loaded in this process, do not load again if (load_assembly_and_get_function_pointer != nullptr) return; @@ -50,10 +50,28 @@ void rSharp_create_domain() { } // STEP 2: Initialize and start the .NET Core runtime - const string_t config_path = STR("./RSharp.runtimeconfig.json"); + + const char* additionalPath = "/RSharp.runtimeconfig.json"; + + size_t libPathLen = strlen(*libPath); + size_t additionalPathLen = strlen(additionalPath); + + char* combinedPath = new char[libPathLen + additionalPathLen + 1]; + + strcpy(combinedPath, *libPath); + strcat(combinedPath, additionalPath); + + size_t length = 0; + mbstowcs_s(&length, nullptr, 0, combinedPath, 0); + char_t* wideStringPath = new char_t[length + 1]; + mbstowcs_s(nullptr, wideStringPath, length + 1, combinedPath, length); + load_assembly_and_get_function_pointer = nullptr; - load_assembly_and_get_function_pointer = get_dotnet_load_assembly(config_path.c_str()); + load_assembly_and_get_function_pointer = get_dotnet_load_assembly(wideStringPath); assert(load_assembly_and_get_function_pointer != nullptr && "Failure: get_dotnet_load_assembly()"); + + delete[] combinedPath; + delete[] wideStringPath; } void rSharp_shutdown_clr() diff --git a/src/rSharp.h b/src/rSharp.h index 29c6fc1..c550af6 100644 --- a/src/rSharp.h +++ b/src/rSharp.h @@ -132,7 +132,7 @@ extern "C" { */ void get_FullTypeName( SEXP p, char ** tname); void rSharp_load_assembly(char ** filename); - void rSharp_create_domain(); + void rSharp_create_domain(char** libPath); int use_rdotnet = 0; From c8bf5fde01840a449cc9d7a95a5900d8e934ca6a Mon Sep 17 00:00:00 2001 From: Ian Peter Du Date: Mon, 4 Mar 2024 16:10:29 +0100 Subject: [PATCH 2/5] update to include ClrFacade.dll --- src/rSharp.cpp | 35 ++++++++++++++++++++--------------- src/rSharp.h | 1 + 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/rSharp.cpp b/src/rSharp.cpp index d914be6..1309255 100644 --- a/src/rSharp.cpp +++ b/src/rSharp.cpp @@ -9,7 +9,7 @@ using string_t = std::basic_string; -const string_t dotnetlib_path = STR("./ClrFacade.dll"); +const char_t* dotnetlib_path = nullptr; const auto loadAssemblyDelegate = STR("ClrFacade.ClrFacade+LoadFromDelegate, ClrFacade"); void* create_instance_fn_ptr = nullptr; void* load_from_fn_ptr = nullptr; @@ -38,6 +38,9 @@ void freeObject(RSharpGenericValue* instance); ///////////////////////////////////////// void rSharp_create_domain(char ** libPath) { + char_t* wideStringPath = MergeLibPath(libPath, "/RSharp.runtimeconfig.json"); + dotnetlib_path = MergeLibPath(libPath, "/ClrFacade.dll"); + // if already loaded in this process, do not load again if (load_assembly_and_get_function_pointer != nullptr) return; @@ -50,9 +53,15 @@ void rSharp_create_domain(char ** libPath) } // STEP 2: Initialize and start the .NET Core runtime + load_assembly_and_get_function_pointer = nullptr; + load_assembly_and_get_function_pointer = get_dotnet_load_assembly(wideStringPath); + assert(load_assembly_and_get_function_pointer != nullptr && "Failure: get_dotnet_load_assembly()"); - const char* additionalPath = "/RSharp.runtimeconfig.json"; + delete[] wideStringPath; +} +char_t* MergeLibPath(char** libPath, char* additionalPath) +{ size_t libPathLen = strlen(*libPath); size_t additionalPathLen = strlen(additionalPath); @@ -66,12 +75,8 @@ void rSharp_create_domain(char ** libPath) char_t* wideStringPath = new char_t[length + 1]; mbstowcs_s(nullptr, wideStringPath, length + 1, combinedPath, length); - load_assembly_and_get_function_pointer = nullptr; - load_assembly_and_get_function_pointer = get_dotnet_load_assembly(wideStringPath); - assert(load_assembly_and_get_function_pointer != nullptr && "Failure: get_dotnet_load_assembly()"); - delete[] combinedPath; - delete[] wideStringPath; + return wideStringPath; } void rSharp_shutdown_clr() @@ -197,7 +202,7 @@ void initializeCreateInstance() auto functionDelegate = STR("ClrFacade.ClrFacade+CreateInstanceDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("CreateInstance"), functionDelegate,//delegate_type_name @@ -213,7 +218,7 @@ void initializeLoadAssembly() auto functionDelegate = STR("ClrFacade.ClrFacade+LoadFromDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("LoadFrom"), loadAssemblyDelegate,//delegate_type_name @@ -229,7 +234,7 @@ void initializeGetFullTypeNameFunction() auto functionDelegate = STR("ClrFacade.ClrFacade+GetObjectTypeNameDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("GetObjectTypeName"), functionDelegate,//delegate_type_name @@ -245,7 +250,7 @@ void initializeGetObjectDirectFunction() auto functionDelegate = STR("ClrFacade.ClrFacade+CurrentObjectDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("CurrentObject"), functionDelegate,//delegate_type_name @@ -261,7 +266,7 @@ void initializeCreateSEXPFunction() auto functionDelegate = STR("ClrFacade.ClrFacade+CreateSexpWrapperDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("CreateSexpWrapperLong"), functionDelegate,//delegate_type_name @@ -278,7 +283,7 @@ void initializeCallInstanceFunction() auto functionDelegate = STR("ClrFacade.ClrFacade+CallInstanceMethodDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("CallInstanceMethod"), functionDelegate,//delegate_type_name @@ -294,7 +299,7 @@ void initializeFreeObjectFunction() auto functionDelegate = STR("ClrFacade.ClrFacade+FreeObjectDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("FreeObject"), functionDelegate,//delegate_type_name @@ -311,7 +316,7 @@ void initializeCallStaticFunction() auto functionDelegate = STR("ClrFacade.ClrFacade+CallStaticMethodDelegate, ClrFacade"); int rc_1 = load_assembly_and_get_function_pointer( - dotnetlib_path.c_str(), + dotnetlib_path, dotnet_type, STR("CallStaticMethod"), functionDelegate,//delegate_type_name diff --git a/src/rSharp.h b/src/rSharp.h index c550af6..6f8e346 100644 --- a/src/rSharp.h +++ b/src/rSharp.h @@ -144,6 +144,7 @@ extern "C" { RSharpGenericValue ConvertToRSharpGenericValue(SEXP s); RSharpGenericValue** sexp_to_parameters(SEXP args); SEXP ConvertToSEXP(RSharpGenericValue& value); +char_t* MergeLibPath(char** libPath, char* additionalPath); #ifndef __cplusplus From 5df90d4046c047ed208fb7f0420284a69f338368 Mon Sep 17 00:00:00 2001 From: Ian Peter Du Date: Tue, 5 Mar 2024 16:27:55 +0100 Subject: [PATCH 3/5] Update from comments --- src/rSharp.cpp | 39 +++++++++++++++++++++------------------ src/rSharp.h | 1 - 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/rSharp.cpp b/src/rSharp.cpp index 1309255..1deb196 100644 --- a/src/rSharp.cpp +++ b/src/rSharp.cpp @@ -9,7 +9,7 @@ using string_t = std::basic_string; -const char_t* dotnetlib_path = nullptr; +const wchar_t* dotnetlib_path = nullptr; const auto loadAssemblyDelegate = STR("ClrFacade.ClrFacade+LoadFromDelegate, ClrFacade"); void* create_instance_fn_ptr = nullptr; void* load_from_fn_ptr = nullptr; @@ -30,16 +30,23 @@ typedef int (CORECLR_DELEGATE_CALLTYPE* CreateSEXPWrapperDelegate)(intptr_t poin typedef int (CORECLR_DELEGATE_CALLTYPE* CreateInstanceDelegate)(const char*, RSharpGenericValue** objects, int num_objects, RSharpGenericValue* returnValue); typedef void (CORECLR_DELEGATE_CALLTYPE* LoadFromDelegate)(const char*); - +wchar_t* MergeLibraryPath(const wchar_t* libraryPath, const wchar_t* additionalPath); void freeObject(RSharpGenericValue* instance); ///////////////////////////////////////// // Initialization and disposal of the CLR ///////////////////////////////////////// -void rSharp_create_domain(char ** libPath) +void rSharp_create_domain(char ** libraryPath) { - char_t* wideStringPath = MergeLibPath(libPath, "/RSharp.runtimeconfig.json"); - dotnetlib_path = MergeLibPath(libPath, "/ClrFacade.dll"); + size_t lengthInWideFormat = 0; + //Gets the length of libPath in terms of a wide string. + mbstowcs_s(&lengthInWideFormat, nullptr, 0, *libraryPath, 0); + wchar_t* wideStringLibraryPath = new wchar_t[lengthInWideFormat + 1]; + //Copies the libraryPath to a wchar_t with the size lengthInWideFormat + mbstowcs_s(nullptr, wideStringLibraryPath, lengthInWideFormat + 1, *libraryPath, lengthInWideFormat); + + wchar_t* wideStringPath = MergeLibraryPath(wideStringLibraryPath, STR("/RSharp.runtimeconfig.json")); + dotnetlib_path = MergeLibraryPath(wideStringLibraryPath, STR("/ClrFacade.dll")); // if already loaded in this process, do not load again if (load_assembly_and_get_function_pointer != nullptr) @@ -58,25 +65,21 @@ void rSharp_create_domain(char ** libPath) assert(load_assembly_and_get_function_pointer != nullptr && "Failure: get_dotnet_load_assembly()"); delete[] wideStringPath; + delete[] wideStringLibraryPath; } -char_t* MergeLibPath(char** libPath, char* additionalPath) +wchar_t* MergeLibraryPath(const wchar_t* libraryPath, const wchar_t* additionalPath) { - size_t libPathLen = strlen(*libPath); - size_t additionalPathLen = strlen(additionalPath); - - char* combinedPath = new char[libPathLen + additionalPathLen + 1]; + size_t libraryPathLength = wcslen(libraryPath); + size_t additionalPathLength = wcslen(additionalPath); + size_t totalLength = libraryPathLength + additionalPathLength + 1; // +1 for null terminator - strcpy(combinedPath, *libPath); - strcat(combinedPath, additionalPath); + wchar_t* mergedPaths = new wchar_t[totalLength]; - size_t length = 0; - mbstowcs_s(&length, nullptr, 0, combinedPath, 0); - char_t* wideStringPath = new char_t[length + 1]; - mbstowcs_s(nullptr, wideStringPath, length + 1, combinedPath, length); + wcscpy_s(mergedPaths, totalLength, libraryPath); + wcscat_s(mergedPaths, totalLength, additionalPath); - delete[] combinedPath; - return wideStringPath; + return mergedPaths; } void rSharp_shutdown_clr() diff --git a/src/rSharp.h b/src/rSharp.h index 6f8e346..c550af6 100644 --- a/src/rSharp.h +++ b/src/rSharp.h @@ -144,7 +144,6 @@ extern "C" { RSharpGenericValue ConvertToRSharpGenericValue(SEXP s); RSharpGenericValue** sexp_to_parameters(SEXP args); SEXP ConvertToSEXP(RSharpGenericValue& value); -char_t* MergeLibPath(char** libPath, char* additionalPath); #ifndef __cplusplus From bf00f7b1068b1f18a51faca1be9e72c623eded7a Mon Sep 17 00:00:00 2001 From: Ian Peter Du Date: Tue, 5 Mar 2024 16:28:54 +0100 Subject: [PATCH 4/5] Update from comments --- src/rSharp.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rSharp.cpp b/src/rSharp.cpp index 1deb196..6d8d725 100644 --- a/src/rSharp.cpp +++ b/src/rSharp.cpp @@ -38,16 +38,6 @@ void freeObject(RSharpGenericValue* instance); ///////////////////////////////////////// void rSharp_create_domain(char ** libraryPath) { - size_t lengthInWideFormat = 0; - //Gets the length of libPath in terms of a wide string. - mbstowcs_s(&lengthInWideFormat, nullptr, 0, *libraryPath, 0); - wchar_t* wideStringLibraryPath = new wchar_t[lengthInWideFormat + 1]; - //Copies the libraryPath to a wchar_t with the size lengthInWideFormat - mbstowcs_s(nullptr, wideStringLibraryPath, lengthInWideFormat + 1, *libraryPath, lengthInWideFormat); - - wchar_t* wideStringPath = MergeLibraryPath(wideStringLibraryPath, STR("/RSharp.runtimeconfig.json")); - dotnetlib_path = MergeLibraryPath(wideStringLibraryPath, STR("/ClrFacade.dll")); - // if already loaded in this process, do not load again if (load_assembly_and_get_function_pointer != nullptr) return; @@ -60,6 +50,16 @@ void rSharp_create_domain(char ** libraryPath) } // STEP 2: Initialize and start the .NET Core runtime + size_t lengthInWideFormat = 0; + //Gets the length of libPath in terms of a wide string. + mbstowcs_s(&lengthInWideFormat, nullptr, 0, *libraryPath, 0); + wchar_t* wideStringLibraryPath = new wchar_t[lengthInWideFormat + 1]; + //Copies the libraryPath to a wchar_t with the size lengthInWideFormat + mbstowcs_s(nullptr, wideStringLibraryPath, lengthInWideFormat + 1, *libraryPath, lengthInWideFormat); + + wchar_t* wideStringPath = MergeLibraryPath(wideStringLibraryPath, STR("/RSharp.runtimeconfig.json")); + dotnetlib_path = MergeLibraryPath(wideStringLibraryPath, STR("/ClrFacade.dll")); + load_assembly_and_get_function_pointer = nullptr; load_assembly_and_get_function_pointer = get_dotnet_load_assembly(wideStringPath); assert(load_assembly_and_get_function_pointer != nullptr && "Failure: get_dotnet_load_assembly()"); From bc1dc86dae78a5be455db82c346e04baa3310441 Mon Sep 17 00:00:00 2001 From: Robert McIntosh <261477+rwmcintosh@users.noreply.github.com> Date: Tue, 5 Mar 2024 14:02:14 -0500 Subject: [PATCH 5/5] Statically link nethost in Windows #30 --- R/zzz.R | 11 ----------- src/Makefile.win.in | 2 -- src/rSharp.vcxproj | 8 +++++--- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/R/zzz.R b/R/zzz.R index 6329ffe..ce345b5 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -75,12 +75,6 @@ loadAndInit <- function(chname, pkgname, libname, srcPkgLibPath=NULL) { # srcPkgLibPath ends with platform separator (e.g. '/') f <- file.path(srcPkgLibPath, paste0(chname, ext)) - # save current working directory - og_wd <- getwd() - - # change working directory to load libs - message("Temporary working directory:", srcPkgLibPath) - setwd(srcPkgLibPath) dyn.load(f) } else { @@ -91,11 +85,6 @@ loadAndInit <- function(chname, pkgname, libname, srcPkgLibPath=NULL) { clrInit(debug_flag!="") appendStartupMsg(paste('Loaded Common Language Runtime version', getClrVersionString())) setRDotNet(TRUE) - - if (exists("og_wd")) { - # restore the original working directory - setwd(og_wd) - } } appendStartupMsg <- function(msg) { diff --git a/src/Makefile.win.in b/src/Makefile.win.in index 59945d8..1d29c47 100644 --- a/src/Makefile.win.in +++ b/src/Makefile.win.in @@ -15,7 +15,6 @@ DOTNET_CMD=dotnet MSB=@MSBUILD_EXE_PATH@ INSTDIR= ../inst -NETHOST=nethost RUNTIMECONFIG=RSharp.runtimeconfig # This can be helpful to diagnose the msbuild procedure @@ -81,7 +80,6 @@ rSharpLib: rSharpLibComp $(ROBOCP_CMD) $$bin_dir $(INSTDIR)/libs/ $$RSHARPBINS;\ - $(ROBOCP_CMD) ./packages/Microsoft.NETCore.App.Host.win-x64.8.0.2/runtimes/win-x64/native $(INSTDIR)/libs/ $(NETHOST).dll $(ROBOCP_CMD) ./ $(INSTDIR)/libs/ $(RUNTIMECONFIG).json; -$(ROBOCP_CMD) ./ClrFacade/bin/$(BuildConfiguration)/net8.0/ $(INSTDIR)/libs/ $(CLR_FACADE_BINS) -$(ROBOCP_CMD) ./ClrFacade/bin/$(BuildConfiguration)/net8.0/ $(INSTDIR)/libs/ $(RDOTNET_BINS) diff --git a/src/rSharp.vcxproj b/src/rSharp.vcxproj index 2699431..edb448f 100644 --- a/src/rSharp.vcxproj +++ b/src/rSharp.vcxproj @@ -241,16 +241,17 @@ Level3 Disabled - _DEBUG;%(PreprocessorDefinitions);MS_CLR;MS_CLR_TLB;USE_COR_RUNTIME_HOST;WINDOWS + %(PreprocessorDefinitions);MS_CLR;MS_CLR_TLB;USE_COR_RUNTIME_HOST;WINDOWS %(AdditionalIncludeDirectories) /TP %(AdditionalOptions) + MultiThreaded NotSet true - Rdll.lib;packages\Microsoft.NETCore.App.Host.win-x64.8.0.2\runtimes\win-x64\native\nethost.lib;%(AdditionalDependencies) + Rdll.lib;packages\Microsoft.NETCore.App.Host.win-x64.8.0.2\runtimes\win-x64\native\libnethost.lib;%(AdditionalDependencies) rSharp-win.def @@ -300,12 +301,13 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions);MS_CLR;MS_CLR_TLB;USE_COR_RUNTIME_HOST;WINDOWS /TP %(AdditionalOptions) + MultiThreaded true true true - packages\Microsoft.NETCore.App.Host.win-x64.8.0.2\runtimes\win-x64\native\nethost.lib;Rdll.lib;%(AdditionalDependencies) + packages\Microsoft.NETCore.App.Host.win-x64.8.0.2\runtimes\win-x64\native\libnethost.lib;Rdll.lib;%(AdditionalDependencies) rSharp-win.def