#ifndef NALL_DL_HPP #define NALL_DL_HPP //dynamic linking support #include #include #include #include #if defined(PLATFORM_XORG) || defined(PLATFORM_MACOSX) #include #elif defined(PLATFORM_WINDOWS) #include #include #endif namespace nall { struct library { explicit operator bool() const { return open(); } bool open() const { return handle; } bool open(const string&, const string& = ""); bool open_absolute(const string&); void* sym(const string&); void close(); library() = default; ~library() { close(); } library& operator=(const library&) = delete; library(const library&) = delete; private: uintptr_t handle = 0; }; #if defined(PLATFORM_XORG) inline bool library::open(const string& name, const string& path) { if(handle) close(); if(path) handle = (uintptr_t)dlopen(string(path, "lib", name, ".so"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string(userpath(), ".local/lib/lib", name, ".so"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".so"), RTLD_LAZY); return handle; } inline bool library::open_absolute(const string& name) { if(handle) close(); handle = (uintptr_t)dlopen(name, RTLD_LAZY); return handle; } inline void* library::sym(const string& name) { if(!handle) return nullptr; return dlsym((void*)handle, name); } inline void library::close() { if(!handle) return; dlclose((void*)handle); handle = 0; } #elif defined(PLATFORM_MACOSX) inline bool library::open(const string& name, const string& path) { if(handle) close(); if(path) handle = (uintptr_t)dlopen(string(path, "lib", name, ".dylib"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string(userpath(), ".local/lib/lib", name, ".dylib"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".dylib"), RTLD_LAZY); return handle; } inline bool library::open_absolute(const string& name) { if(handle) close(); handle = (uintptr_t)dlopen(name, RTLD_LAZY); return handle; } inline void* library::sym(const string& name) { if(!handle) return nullptr; return dlsym((void*)handle, name); } inline void library::close() { if(!handle) return; dlclose((void*)handle); handle = 0; } #elif defined(PLATFORM_WINDOWS) inline bool library::open(const string& name, const string& path) { if(handle) close(); if(path) { string filepath = {path, name, ".dll"}; handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); } if(!handle) { string filepath = {name, ".dll"}; handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); } return handle; } inline bool library::open_absolute(const string& name) { if(handle) close(); handle = (uintptr_t)LoadLibraryW(utf16_t(name)); return handle; } inline void* library::sym(const string& name) { if(!handle) return nullptr; return (void*)GetProcAddress((HMODULE)handle, name); } inline void library::close() { if(!handle) return; FreeLibrary((HMODULE)handle); handle = 0; } #else inline bool library::open(const string&, const string&) { return false; } inline bool library::open_absolute(const string&) { return false; } inline void* library::sym(const string&) { return nullptr; } inline void library::close() {} #endif } #endif