From 0696cd8472672a1150663bc7dd5e8542ec12baf6 Mon Sep 17 00:00:00 2001 From: Ge Wang Date: Fri, 1 Nov 2024 21:47:22 -0700 Subject: [PATCH] add DLL search path resolution for chugin dependencies (windows) (#474) * add AddDllDirectory() functionality for chugin deps (windows) * add option to activate add-dll-dir search paths * use platformPath in import_chugin_opt() --- src/core/chuck_compile.cpp | 35 +++++++++++++++++++++++++++++++++-- src/core/chuck_dl.cpp | 9 +++++++-- src/core/chuck_type.cpp | 6 +++--- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/core/chuck_compile.cpp b/src/core/chuck_compile.cpp index b815a0252..881ac1453 100644 --- a/src/core/chuck_compile.cpp +++ b/src/core/chuck_compile.cpp @@ -1524,6 +1524,8 @@ t_CKBOOL Chuck_Compiler::import_chugin_opt( const string & path, const string & { // get env Chuck_Env * env = this->env(); + // platform-specific path (below: will use the appropriate '/' vs '\\') + string platformPath = path; // NOTE this (verbose >= 5) is more informative if the chugin crashes, we can see the name EM_log( CK_LOG_INFO, "@import loading [chugin] %s...", name.c_str() ); @@ -1535,8 +1537,24 @@ t_CKBOOL Chuck_Compiler::import_chugin_opt( const string & path, const string & // clear error string errorStr = ""; +#if defined(__PLATFORM_WINDOWS__) + // replace '/' with '\\' + std::replace( platformPath.begin(), platformPath.end(), '/', '\\' ); + // the dll search path to add + string dll_path = extract_filepath_dir( platformPath ); + // the relateive _deps directory + string dll_deps_path = dll_path + "_deps\\"; + // convert to wchar + wstring dll_pathw = wstring( dll_path.begin(), dll_path.end() ); + wstring dll_deps_pathw = wstring( dll_deps_path.begin(), dll_deps_path.end() ); + // add to the dll search path, for resolving the chugin's own DLL dependencies + DLL_DIRECTORY_COOKIE cookie_path = AddDllDirectory( dll_pathw.c_str() ); + // add the relateive _deps directory to the search path as well + DLL_DIRECTORY_COOKIE cookie_deps_path = AddDllDirectory( dll_deps_pathw.c_str() ); +#endif + // load (but don't query yet; lazy mode == TRUE) - if( dll->load( path.c_str(), CK_QUERY_FUNC, TRUE) ) + if( dll->load( platformPath.c_str(), CK_QUERY_FUNC, TRUE) ) { // probe it dll->probe(); @@ -1575,6 +1593,8 @@ t_CKBOOL Chuck_Compiler::import_chugin_opt( const string & path, const string & } EM_log( CK_LOG_HERALD, "%s '%s'...", TC::blue("skipping",true).c_str(), path.c_str() ); EM_poplog(); + // set error string + errorStr = dll->last_error(); // go to error for cleanup goto error; } @@ -1589,6 +1609,8 @@ t_CKBOOL Chuck_Compiler::import_chugin_opt( const string & path, const string & EM_pushlog(); EM_log( CK_LOG_HERALD, "reason: %s", TC::orange(dll->last_error(),true).c_str() ); EM_poplog(); + // set error string + errorStr = dll->last_error(); // go to error for cleanup goto error; } @@ -1601,6 +1623,11 @@ t_CKBOOL Chuck_Compiler::import_chugin_opt( const string & path, const string & m_importRegistry.commit( dll ); // commit operator overloads | 1.5.1.5 env->op_registry.preserve(); +#if defined(__PLATFORM_WINDOWS__) + // undo the AddDllDirectory() + if( cookie_path ) RemoveDllDirectory( cookie_path ); + if( cookie_deps_path ) RemoveDllDirectory( cookie_deps_path ); +#endif // return home successful return TRUE; @@ -1609,7 +1636,11 @@ t_CKBOOL Chuck_Compiler::import_chugin_opt( const string & path, const string & CK_SAFE_DELETE( dll ); // rollback operator overloads | 1.5.1.5 env->op_registry.reset2local(); - +#if defined(__PLATFORM_WINDOWS__) + // undo the AddDllDirectory() + if( cookie_path ) RemoveDllDirectory( cookie_path ); + if( cookie_deps_path ) RemoveDllDirectory( cookie_deps_path ); +#endif return FALSE; } diff --git a/src/core/chuck_dl.cpp b/src/core/chuck_dl.cpp index a900826d8..7cfc9120b 100644 --- a/src/core/chuck_dl.cpp +++ b/src/core/chuck_dl.cpp @@ -3011,11 +3011,16 @@ extern "C" void *dlopen( const char *path, int mode ) { #ifndef __CHUNREAL_ENGINE__ - return (void *)LoadLibrary(path); + // 1.5.4.0 (ge) change from LoadLibrary to LoadLibraryEx to specific + // LOAD_LIBRARY_SEARCH_DEFAULT_DIRS -- this is needed, apparently, + // to take directories added by AddDllDirectory() into account, which + // is needed to load DLL dependencies of chugins... + // https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-adddlldirectory + return (void *)LoadLibraryEx( path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS ); #else // 1.5.0.0 (ge) | #chunreal; explicitly call ASCII version // the build envirnment seems to force UNICODE - return (void *)LoadLibraryA(path); + return (void *)LoadLibraryExA( path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS ); #endif } diff --git a/src/core/chuck_type.cpp b/src/core/chuck_type.cpp index 9a44e9916..aab1f872c 100644 --- a/src/core/chuck_type.cpp +++ b/src/core/chuck_type.cpp @@ -735,9 +735,9 @@ t_CKBOOL type_engine_init( Chuck_Carrier * carrier ) return TRUE; -error: - EM_error2( 0, "(internal error) during type initialization..." ); - EM_error2( 0, "...bailing out; please contact the ChucK Team" ); +// error: +// EM_error2( 0, "(internal error) during type initialization..." ); +// EM_error2( 0, "...bailing out; please contact the ChucK Team" ); return FALSE; }