diff options
Diffstat (limited to 'src/osd/modules/lib')
-rw-r--r-- | src/osd/modules/lib/osdlib.h | 46 | ||||
-rw-r--r-- | src/osd/modules/lib/osdlib_macosx.cpp | 74 | ||||
-rw-r--r-- | src/osd/modules/lib/osdlib_unix.cpp | 75 | ||||
-rw-r--r-- | src/osd/modules/lib/osdlib_win32.cpp | 84 |
4 files changed, 278 insertions, 1 deletions
diff --git a/src/osd/modules/lib/osdlib.h b/src/osd/modules/lib/osdlib.h index f4a632dbbd1..64bd556cd3c 100644 --- a/src/osd/modules/lib/osdlib.h +++ b/src/osd/modules/lib/osdlib.h @@ -19,6 +19,10 @@ #ifndef __OSDLIB__ #define __OSDLIB__ +#include <string> +#include <type_traits> +#include <vector> + /*----------------------------------------------------------------------------- osd_process_kill: kill the current process @@ -30,8 +34,10 @@ None. -----------------------------------------------------------------------------*/ + void osd_process_kill(void); + /*----------------------------------------------------------------------------- osd_setenv: set environment variable @@ -48,14 +54,52 @@ void osd_process_kill(void); int osd_setenv(const char *name, const char *value, int overwrite); + /*----------------------------------------------------------------------------- osd_get_clipboard_text: retrieves text from the clipboard Return value: the returned string needs to be osd_free()-ed! - -----------------------------------------------------------------------------*/ + char *osd_get_clipboard_text(void); + +/*----------------------------------------------------------------------------- + dynamic_module: load functions from optional shared libraries + + Notes: + + - Supports Mac OS X, Unix and Windows (both desktop and Windows + Store universal applications) + - A symbol can be searched in a list of libraries (e.g. more + revisions of a same library) +-----------------------------------------------------------------------------*/ + +namespace osd { + +class dynamic_module +{ +public: + typedef std::unique_ptr<dynamic_module> ptr; + + static ptr open(std::vector<std::string> &&libraries); + + virtual ~dynamic_module() { }; + + template <typename T> + typename std::enable_if<std::is_pointer<T>::value, T>::type bind(char const *symbol) + { + return reinterpret_cast<T>(get_symbol_address(symbol)); + } + +protected: + typedef void (*generic_fptr_t)(); + + virtual generic_fptr_t get_symbol_address(char const *symbol) = 0; +}; + +} // namespace osd + #endif /* __OSDLIB__ */ diff --git a/src/osd/modules/lib/osdlib_macosx.cpp b/src/osd/modules/lib/osdlib_macosx.cpp index 07cfa05226a..b3a7ed642e3 100644 --- a/src/osd/modules/lib/osdlib_macosx.cpp +++ b/src/osd/modules/lib/osdlib_macosx.cpp @@ -13,6 +13,12 @@ #include <sys/mman.h> #include <sys/types.h> #include <signal.h> +#include <dlfcn.h> + +#include <codecvt> +#include <iomanip> +#include <memory> + #include <mach/mach.h> #include <mach/mach_time.h> @@ -215,3 +221,71 @@ char *osd_get_clipboard_text(void) return result; } + +//============================================================ +// dynamic_module_posix_impl +//============================================================ + +namespace osd { + +class dynamic_module_posix_impl : public dynamic_module +{ +public: + dynamic_module_posix_impl(std::vector<std::string> &libraries) + : m_module(nullptr) + { + m_libraries = libraries; + } + + virtual ~dynamic_module_posix_impl() override + { + if (m_module != nullptr) + dlclose(m_module); + }; + +protected: + virtual generic_fptr_t get_symbol_address(char const *symbol) override + { + /* + * given a list of libraries, if a first symbol is successfully loaded from + * one of them, all additional symbols will be loaded from the same library + */ + if (m_module) + { + return reinterpret_cast<generic_fptr_t>(dlsym(m_module, symbol)); + } + + for (auto const &library : m_libraries) + { + void *module = dlopen(library.c_str(), RTLD_LAZY); + + if (module != nullptr) + { + generic_fptr_t function = reinterpret_cast<generic_fptr_t>(dlsym(module, symbol)); + + if (function != nullptr) + { + m_module = module; + return function; + } + else + { + dlclose(module); + } + } + } + + return nullptr; + } + +private: + std::vector<std::string> m_libraries; + void * m_module; +}; + +dynamic_module::ptr dynamic_module::open(std::vector<std::string> &&names) +{ + return std::make_unique<dynamic_module_posix_impl>(names); +} + +} // namespace osd diff --git a/src/osd/modules/lib/osdlib_unix.cpp b/src/osd/modules/lib/osdlib_unix.cpp index 52999835a1c..81d9967ff64 100644 --- a/src/osd/modules/lib/osdlib_unix.cpp +++ b/src/osd/modules/lib/osdlib_unix.cpp @@ -13,12 +13,19 @@ #include <sys/mman.h> #include <sys/types.h> #include <signal.h> +#include <dlfcn.h> + +#include <codecvt> +#include <iomanip> +#include <memory> + // MAME headers #include "osdcore.h" #include "osdlib.h" #include <SDL2/SDL.h> + //============================================================ // osd_getenv //============================================================ @@ -159,3 +166,71 @@ char *osd_get_clipboard_text(void) } #endif + +//============================================================ +// dynamic_module_posix_impl +//============================================================ + +namespace osd { + +class dynamic_module_posix_impl : public dynamic_module +{ +public: + dynamic_module_posix_impl(std::vector<std::string> &libraries) + : m_module(nullptr) + { + m_libraries = libraries; + } + + virtual ~dynamic_module_posix_impl() override + { + if (m_module != nullptr) + dlclose(m_module); + }; + +protected: + virtual generic_fptr_t get_symbol_address(char const *symbol) override + { + /* + * given a list of libraries, if a first symbol is successfully loaded from + * one of them, all additional symbols will be loaded from the same library + */ + if (m_module) + { + return reinterpret_cast<generic_fptr_t>(dlsym(m_module, symbol)); + } + + for (auto const &library : m_libraries) + { + void *module = dlopen(library.c_str(), RTLD_LAZY); + + if (module != nullptr) + { + generic_fptr_t function = reinterpret_cast<generic_fptr_t>(dlsym(module, symbol)); + + if (function != nullptr) + { + m_module = module; + return function; + } + else + { + dlclose(module); + } + } + } + + return nullptr; + } + +private: + std::vector<std::string> m_libraries; + void * m_module; +}; + +dynamic_module::ptr dynamic_module::open(std::vector<std::string> &&names) +{ + return std::make_unique<dynamic_module_posix_impl>(names); +} + +} // namespace osd diff --git a/src/osd/modules/lib/osdlib_win32.cpp b/src/osd/modules/lib/osdlib_win32.cpp index f778977614a..e65509cc436 100644 --- a/src/osd/modules/lib/osdlib_win32.cpp +++ b/src/osd/modules/lib/osdlib_win32.cpp @@ -17,6 +17,8 @@ #include <unistd.h> #endif +#include <memory> + // MAME headers #include "osdlib.h" #include "osdcomm.h" @@ -314,3 +316,85 @@ char *osd_get_clipboard_text(void) return result; } + +//============================================================ +// osd_dynamic_bind +//============================================================ + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +// for classic desktop applications +#define load_library(filename) LoadLibrary(filename) +#else +// for Windows Store universal applications +#define load_library(filename) LoadPackagedLibrary(filename, 0) +#endif + +namespace osd { + +class dynamic_module_win32_impl : public dynamic_module +{ +public: + dynamic_module_win32_impl(std::vector<std::string> &libraries) + : m_module(nullptr) + { + m_libraries = libraries; + } + + virtual ~dynamic_module_win32_impl() override + { + if (m_module != nullptr) + FreeLibrary(m_module); + }; + +protected: + virtual generic_fptr_t get_symbol_address(char const *symbol) override + { + /* + * given a list of libraries, if a first symbol is successfully loaded from + * one of them, all additional symbols will be loaded from the same library + */ + if (m_module) + { + return reinterpret_cast<generic_fptr_t>(GetProcAddress(m_module, symbol)); + } + + for (auto const &library : m_libraries) + { + TCHAR *tempstr = tstring_from_utf8(library.c_str()); + if (!tempstr) + return nullptr; + + HMODULE module = load_library(tempstr); + + osd_free(tempstr); + + if (module != nullptr) + { + generic_fptr_t function = reinterpret_cast<generic_fptr_t>(GetProcAddress(module, symbol)); + + if (function != nullptr) + { + m_module = module; + return function; + } + else + { + FreeLibrary(module); + } + } + } + + return nullptr; + } + +private: + std::vector<std::string> m_libraries; + HMODULE m_module; +}; + +dynamic_module::ptr dynamic_module::open(std::vector<std::string> &&names) +{ + return std::make_unique<dynamic_module_win32_impl>(names); +} + +} // namespace osd |