diff --git a/dtool/src/dtoolutil/load_dso.cxx b/dtool/src/dtoolutil/load_dso.cxx index 9efab1613a..f41d970b39 100644 --- a/dtool/src/dtoolutil/load_dso.cxx +++ b/dtool/src/dtoolutil/load_dso.cxx @@ -18,6 +18,21 @@ #include "load_dso.h" +static Filename resolve_dso(const DSearchPath &path, const Filename &filename) { + if (filename.is_local()) { + if (path.is_empty()|| + ((path.get_num_directories()==1)&&(path.get_directory(0)=="."))) { + Filename dtoolpath = ExecutionEnvironment::get_dtool_name(); + DSearchPath spath(dtoolpath.get_dirname()); + return spath.find_file(filename); + } else { + return path.find_file(filename); + } + } else { + return filename; + } +} + #if defined(WIN32) /* begin Win32-specific code */ @@ -25,9 +40,30 @@ #include #undef WINDOWS_LEAN_AND_MEAN +// Loads in a dynamic library like an .so or .dll. Returns NULL if +// failure, otherwise on success. If the filename is not absolute, +// searches the path. If the path is empty, searches the dtool +// directory. + void * -load_dso(const Filename &filename) { - string os_specific = filename.to_os_specific(); +load_dso(const DSearchPath &path, const Filename &filename) { + Filename abspath = resolve_dso(path, filename); + if (!abspath.is_regular_file()) { + return NULL; + } + string os_specific = abspath.to_os_specific(); + + // Try using LoadLibraryEx, if possible. + typedef HMODULE (WINAPI *tLoadLibraryEx)(LPCTSTR, HANDLE, DWORD); + tLoadLibraryEx pLoadLibraryEx; + HINSTANCE hLib = LoadLibrary("kernel32.dll"); + if (hLib) { + pLoadLibraryEx = (tLoadLibraryEx)GetProcAddress(hLib, "LoadLibraryExA"); + if (pLoadLibraryEx) { + return pLoadLibraryEx(os_specific.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + } + return LoadLibrary(os_specific.c_str()); } @@ -67,15 +103,15 @@ load_dso_error() { #include #include -void * load_dso(const Filename &filename) +void * load_dso(const DSearchPath &path, const Filename &filename) { - - std::string fname = filename.to_os_specific(); - void * answer = dlopen(fname.c_str(),RTLD_NOW| RTLD_LOCAL); - //void * answer = dlopen(fname.c_str(),RTLD_NOW); - - return answer; - + Filename abspath = resolve_dso(path, filename); + if (!abspath.is_regular_file()) { + return NULL; + } + string fname = abspath.to_os_specific(); + void * answer = dlopen(fname.c_str(),RTLD_NOW| RTLD_LOCAL); + return answer; } string @@ -90,8 +126,12 @@ load_dso_error() { #include void * -load_dso(const Filename &filename) { - string os_specific = filename.to_os_specific(); +load_dso(const DSearchPath &path, const Filename &filename) { + Filename abspath = resolve_dso(path, filename); + if (!abspath.is_regular_file()) { + return NULL; + } + string os_specific = abspath.to_os_specific(); return dlopen(os_specific.c_str(), RTLD_NOW | RTLD_GLOBAL); } diff --git a/dtool/src/dtoolutil/load_dso.h b/dtool/src/dtoolutil/load_dso.h index 88b763534c..354b1bdd99 100644 --- a/dtool/src/dtoolutil/load_dso.h +++ b/dtool/src/dtoolutil/load_dso.h @@ -20,14 +20,16 @@ #define LOAD_DSO_H #include "dtoolbase.h" - +#include "dSearchPath.h" #include "filename.h" // Loads in a dynamic library like an .so or .dll. Returns NULL if -// failure, otherwise on success. +// failure, otherwise on success. If the filename is not absolute, +// searches the path. If the path is empty, searches the dtool +// directory. EXPCL_DTOOL void * -load_dso(const Filename &filename); +load_dso(const DSearchPath &path, const Filename &filename); // true indicates success EXPCL_DTOOL bool diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx index 63d0fd4dfe..74d692f842 100644 --- a/dtool/src/interrogate/interrogate_module.cxx +++ b/dtool/src/interrogate/interrogate_module.cxx @@ -333,7 +333,7 @@ int main(int argc, char *argv[]) Filename pathname = argv[i]; pathname.set_type(Filename::T_dso); nout << "Loading " << pathname << "\n"; - void *dl = load_dso(pathname); + void *dl = load_dso(DSearchPath(), pathname); if (dl == NULL) { nout << "Unable to load: " << load_dso_error() << "\n"; exit(1); diff --git a/dtool/src/test_interrogate/test_interrogate.cxx b/dtool/src/test_interrogate/test_interrogate.cxx index 0adef25c73..2223aa8bf5 100644 --- a/dtool/src/test_interrogate/test_interrogate.cxx +++ b/dtool/src/test_interrogate/test_interrogate.cxx @@ -534,7 +534,7 @@ main(int argc, char *argv[]) { // Otherwise, assume it's a shared library, and try to load it. Filename pathname = Filename::dso_filename(argv[i]); cerr << "Loading " << pathname << "\n"; - void *dl = load_dso(pathname); + void *dl = load_dso(DSearchPath(), pathname); if (dl == NULL) { cerr << "Unable to load: " << load_dso_error() << "\n"; return_status++; diff --git a/panda/src/audio/audioManager.cxx b/panda/src/audio/audioManager.cxx index f17abe204a..828cf05e69 100644 --- a/panda/src/audio/audioManager.cxx +++ b/panda/src/audio/audioManager.cxx @@ -62,7 +62,7 @@ PT(AudioManager) AudioManager::create_AudioManager() { "lib"+string(audio_library_name)+".so"); dl_name.to_os_specific(); audio_debug(" dl_name=\""<info() << "loading texture filter: " << dlname.to_os_specific() << endl; - void *tmp = load_dso(dlname); + void *tmp = load_dso(plugin_path.get_value(), dlname); if (tmp == (void *)NULL) { gobj_cat.info() << "Unable to load: " << load_dso_error() << endl; diff --git a/panda/src/pgraph/loader.cxx b/panda/src/pgraph/loader.cxx index a3361e9a87..16e8ce0e6f 100644 --- a/panda/src/pgraph/loader.cxx +++ b/panda/src/pgraph/loader.cxx @@ -326,7 +326,7 @@ load_file_types() { Filename dlname = Filename::dso_filename("lib" + name + ".so"); loader_cat.info() << "loading file type module: " << name << endl; - void *tmp = load_dso(dlname); + void *tmp = load_dso(plugin_path.get_value(), dlname); if (tmp == (void *)NULL) { loader_cat.warning() << "Unable to load " << dlname.to_os_specific() diff --git a/panda/src/pgraph/loaderFileTypeRegistry.cxx b/panda/src/pgraph/loaderFileTypeRegistry.cxx index 52820053c5..df3071c1b4 100644 --- a/panda/src/pgraph/loaderFileTypeRegistry.cxx +++ b/panda/src/pgraph/loaderFileTypeRegistry.cxx @@ -174,7 +174,7 @@ get_type_from_extension(const string &extension) { loader_cat->info() << "loading file type module: " << name << endl; - void *tmp = load_dso(dlname); + void *tmp = load_dso(plugin_path.get_value(), dlname); if (tmp == (void *)NULL) { loader_cat->warning() << "Unable to load " << dlname.to_os_specific() << ": " diff --git a/panda/src/putil/config_util.cxx b/panda/src/putil/config_util.cxx index 338e128b22..45a4b9eee1 100644 --- a/panda/src/putil/config_util.cxx +++ b/panda/src/putil/config_util.cxx @@ -80,6 +80,11 @@ ConfigVariableSearchPath texture_path ConfigVariableSearchPath sound_path ("sound-path", PRC_DESC("The directories to search for sound and music files to be loaded.")); +ConfigVariableSearchPath plugin_path +("plugin-path", + PRC_DESC("The directories to search for plugin shared libraries.")); + + ConfigureFn(config_util) { init_libputil(); @@ -113,6 +118,11 @@ get_sound_path() { return sound_path; } +ConfigVariableSearchPath & +get_plugin_path() { + return plugin_path; +} + ConfigVariableDouble sleep_precision ("sleep-precision", 0.01, PRC_DESC("This is the accuracy within which we can expect select() to " diff --git a/panda/src/putil/config_util.h b/panda/src/putil/config_util.h index 42054aa708..b513f25075 100644 --- a/panda/src/putil/config_util.h +++ b/panda/src/putil/config_util.h @@ -46,6 +46,7 @@ extern EXPCL_PANDA_PUTIL ConfigVariableEnum bam_texture_mode; extern EXPCL_PANDA_PUTIL ConfigVariableSearchPath model_path; extern EXPCL_PANDA_PUTIL ConfigVariableSearchPath texture_path; extern EXPCL_PANDA_PUTIL ConfigVariableSearchPath sound_path; +extern EXPCL_PANDA_PUTIL ConfigVariableSearchPath plugin_path; // The above variables are also shadowed by these functions, so that // they can easily be accessed in the interpreter (e.g. Python). @@ -53,6 +54,7 @@ BEGIN_PUBLISH EXPCL_PANDA_PUTIL ConfigVariableSearchPath &get_model_path(); EXPCL_PANDA_PUTIL ConfigVariableSearchPath &get_texture_path(); EXPCL_PANDA_PUTIL ConfigVariableSearchPath &get_sound_path(); +EXPCL_PANDA_PUTIL ConfigVariableSearchPath &get_plugin_path(); END_PUBLISH extern ConfigVariableDouble clock_frame_rate;