diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/ctx.cpp | 78 | ||||
-rw-r--r-- | src/ctx.hpp | 3 |
3 files changed, 81 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index 99fab21..e29263b 100644 --- a/configure.ac +++ b/configure.ac @@ -101,6 +101,8 @@ AS_CASE(["${host_os}"], AC_DEFINE([XS_HAVE_ANDROID], [1], [Have Android OS]) ] ) + + AC_CHECK_LIB([dl], [dlopen]) ], [*solaris*], [ # Define on Solaris to enable all library features diff --git a/src/ctx.cpp b/src/ctx.cpp index 99a2b3c..f5d9719 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -26,6 +26,11 @@ #include <unistd.h> #endif +#if defined XS_HAVE_LINUX +#include <dlfcn.h> +#include <dirent.h> +#endif + #include <new> #include <string.h> @@ -109,6 +114,69 @@ next: BOOL brc = FindClose (fh); win_assert (brc != 0); +#elif defined XS_HAVE_LINUX + + // Load all the installed plug-ins. + std::string path (XS_PREFIX_PATH); + path += "/lib/xs/plugins"; + + DIR *dp = opendir (path.c_str ()); + if (!dp && errno == ENOENT) + return; + errno_assert (dp); + + dirent dir, *dirp; + while (true) { + rc = readdir_r (dp, &dir, &dirp); + assert (rc == 0); + if (!dirp) + break; + if (dir.d_type == DT_REG) { + + // Ignore the files without .xsp extension. + std::string file = dir.d_name; + if (file.size () < 4) + continue; + if (file.substr (file.size () - 4) != ".xsp") + continue; + + // Open the specified dynamic library. + std::string filename = path + "/" + file; + void *dl = dlopen (filename.c_str (), RTLD_LOCAL | RTLD_NOW); + if (!dl) + continue; + + // Find the initial entry point in the library. void pointer + // returned by dlsym is converted to function pointer using + // "union cast". There's no other way to do that as POSIX and + // C++ standards collide at this spot. + file = std::string ("xsp_") + file.substr (0, file.size () - 4) + + "_init"; + dlerror (); + union { + void *pdata; + void *(*pfunc) (); + } initfn; + initfn.pdata = dlsym (dl, file.c_str ()); + if (!initfn.pdata) + continue; + + // Plug the extension into the context. + int rc = plug (initfn.pfunc ()); + if (rc != 0) { + dlclose (dl); + continue; + } + + // Store the library handle so that we can unload it + // when context is terminated. + opt_sync.lock (); + plugins.push_back (dl); + opt_sync.unlock (); + } + } + closedir (dp); + #endif } @@ -186,13 +254,19 @@ int xs::ctx_t::terminate () slot_sync.unlock (); // Unload any dynamically loaded extension libraries. - opt_sync.lock (); #if defined XS_HAVE_WINDOWS + opt_sync.lock (); for (plugins_t::iterator it = plugins.begin (); it != plugins.end (); ++it) FreeLibrary (*it); -#endif opt_sync.unlock (); +#elif defined XS_HAVE_LINUX + opt_sync.lock (); + for (plugins_t::iterator it = plugins.begin (); + it != plugins.end (); ++it) + dlclose (*it); + opt_sync.unlock (); +#endif // Deallocate the resources. delete this; diff --git a/src/ctx.hpp b/src/ctx.hpp index 75b36bd..7b0b74b 100644 --- a/src/ctx.hpp +++ b/src/ctx.hpp @@ -173,6 +173,9 @@ namespace xs #if defined XS_HAVE_WINDOWS typedef std::vector <HMODULE> plugins_t; plugins_t plugins; +#elif defined XS_HAVE_LINUX + typedef std::vector <void*> plugins_t; + plugins_t plugins; #endif // List of all filters plugged into the context. |