#ifndef _library__loadlib__hpp__included__ #define _library__loadlib__hpp__included__ #include #include #include #include "threads.hpp" #if defined(_WIN32) || defined(_WIN64) #include #endif namespace loadlib { threads::lock& global_mutex(); /** * A loaded library. */ class library { public: /** * Construct a NULL library. */ library() { lib = NULL; } /** * Load a new library. * * Parameter filename: The name of file. * Throws std::bad_alloc: Not enough memory. * Throws std::runtime_error: Error loading shared library. */ library(const std::string& filename) throw(std::bad_alloc, std::runtime_error) { lib = new internal(filename); } /** * Unload a library. */ ~library() throw() { threads::alock h(global_mutex()); if(lib && !--lib->refs) delete lib; } /** * Look up a symbol. * * Parameter symbol: The symbol to look up. * Returns: The symbol value. * Throws std::bad_alloc: Not enough memory. * Throws std::runtime_error: Error looking up the symbol. */ void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error) { threads::alock h(global_mutex()); if(!lib) throw std::runtime_error("Symbol '" + symbol + "' not found"); return (*lib)[symbol]; } /** * See what libraries are called on this platform. * * Returns: The name of library. */ static const std::string& name() throw(); /** * See what standard library extension is on this platform. * * Returns: The extension of library. */ static const std::string& extension() throw(); /** * Copy ctor. */ library(const library& r) { threads::alock h(global_mutex()); lib = r.lib; if(lib) ++lib->refs; } library& operator=(const library& r) { if(lib == r.lib) return *this; threads::alock h(global_mutex()); if(lib && !--lib->refs) delete lib; lib = r.lib; if(lib) ++lib->refs; return *this; } private: struct internal { internal(const std::string& filename) throw(std::bad_alloc, std::runtime_error); ~internal() throw(); void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error); internal(const internal&); internal& operator=(const internal&); #if defined(_WIN32) || defined(_WIN64) HMODULE handle; #elif !defined(NO_DLFCN) void* handle; #endif size_t refs; }; internal* lib; }; /** * A program module. */ class module { template struct fntype { typedef T(*t)(U...); }; public: /** * Symbol definition. */ struct symbol { const char* name; void* address; }; /** * Construct a module from list of symbols. */ module(std::initializer_list symbols, std::function init_fn); /** * Construct a module from library. */ module(library lib); /** * Copy ctor */ module(const module& mod); /** * Dtor. */ ~module(); /** * Symbol lookup. */ void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error); /** * Variable symbol lookup. */ template T* var(const std::string& symbol) const throw(std::bad_alloc, std::runtime_error) { return (T*)(*this)[symbol]; } /** * Function symbol lookup. */ template typename fntype::t fn(const std::string& symbol) const throw(std::bad_alloc, std::runtime_error) { return (typename fntype::t)(*this)[symbol]; } /** * Run all not ran initialization functions. */ static void run_initializers(); private: bool dynamic; library lib; std::map symbols; std::function init; }; } #endif