2012-10-14 23:55:36 +03:00
|
|
|
#ifndef _library__loadlib__hpp__included__
|
|
|
|
#define _library__loadlib__hpp__included__
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <stdexcept>
|
2013-12-19 16:23:50 +02:00
|
|
|
#include <map>
|
2014-03-23 09:45:42 +02:00
|
|
|
#include "threads.hpp"
|
2012-10-14 23:55:36 +03:00
|
|
|
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2013-12-19 16:23:50 +02:00
|
|
|
namespace loadlib
|
|
|
|
{
|
2014-03-23 09:45:42 +02:00
|
|
|
threads::lock& global_mutex();
|
2013-12-19 16:23:50 +02:00
|
|
|
|
2012-10-14 23:55:36 +03:00
|
|
|
/**
|
|
|
|
* A loaded library.
|
|
|
|
*/
|
2013-12-19 16:23:50 +02:00
|
|
|
class library
|
2012-10-14 23:55:36 +03:00
|
|
|
{
|
|
|
|
public:
|
2013-12-19 16:23:50 +02:00
|
|
|
/**
|
|
|
|
* Construct a NULL library.
|
|
|
|
*/
|
|
|
|
library()
|
|
|
|
{
|
|
|
|
lib = NULL;
|
|
|
|
}
|
2012-10-14 23:55:36 +03:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-12-19 16:23:50 +02:00
|
|
|
library(const std::string& filename) throw(std::bad_alloc, std::runtime_error)
|
|
|
|
{
|
|
|
|
lib = new internal(filename);
|
|
|
|
}
|
2012-10-14 23:55:36 +03:00
|
|
|
/**
|
|
|
|
* Unload a library.
|
|
|
|
*/
|
2013-12-19 16:23:50 +02:00
|
|
|
~library() throw()
|
|
|
|
{
|
2014-03-23 09:45:42 +02:00
|
|
|
threads::alock h(global_mutex());
|
2013-12-19 16:23:50 +02:00
|
|
|
if(lib && !--lib->refs)
|
|
|
|
delete lib;
|
|
|
|
}
|
2012-10-14 23:55:36 +03:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-12-19 16:23:50 +02:00
|
|
|
void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error)
|
|
|
|
{
|
2014-03-23 09:45:42 +02:00
|
|
|
threads::alock h(global_mutex());
|
2013-12-19 16:23:50 +02:00
|
|
|
if(!lib) throw std::runtime_error("Symbol '" + symbol + "' not found");
|
|
|
|
return (*lib)[symbol];
|
|
|
|
}
|
2012-10-14 23:55:36 +03:00
|
|
|
/**
|
|
|
|
* See what libraries are called on this platform.
|
|
|
|
*
|
|
|
|
* Returns: The name of library.
|
|
|
|
*/
|
2013-12-19 16:23:50 +02:00
|
|
|
static const std::string& name() throw();
|
2013-03-25 11:35:41 +02:00
|
|
|
/**
|
|
|
|
* See what standard library extension is on this platform.
|
|
|
|
*
|
|
|
|
* Returns: The extension of library.
|
|
|
|
*/
|
2013-12-19 16:23:50 +02:00
|
|
|
static const std::string& extension() throw();
|
|
|
|
/**
|
|
|
|
* Copy ctor.
|
|
|
|
*/
|
|
|
|
library(const library& r)
|
|
|
|
{
|
2014-03-23 09:45:42 +02:00
|
|
|
threads::alock h(global_mutex());
|
2013-12-19 16:23:50 +02:00
|
|
|
lib = r.lib;
|
|
|
|
if(lib) ++lib->refs;
|
|
|
|
}
|
|
|
|
library& operator=(const library& r)
|
|
|
|
{
|
|
|
|
if(lib == r.lib)
|
|
|
|
return *this;
|
2014-03-23 09:45:42 +02:00
|
|
|
threads::alock h(global_mutex());
|
2013-12-19 16:23:50 +02:00
|
|
|
if(lib && !--lib->refs)
|
|
|
|
delete lib;
|
|
|
|
lib = r.lib;
|
|
|
|
if(lib) ++lib->refs;
|
|
|
|
return *this;
|
|
|
|
}
|
2014-10-31 23:24:23 +02:00
|
|
|
std::string get_libname() const { return lib->libname; }
|
2012-10-14 23:55:36 +03:00
|
|
|
private:
|
2013-12-19 16:23:50 +02:00
|
|
|
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&);
|
2012-10-14 23:55:36 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2013-12-19 16:23:50 +02:00
|
|
|
HMODULE handle;
|
2012-10-14 23:55:36 +03:00
|
|
|
#elif !defined(NO_DLFCN)
|
2013-12-19 16:23:50 +02:00
|
|
|
void* handle;
|
2012-10-14 23:55:36 +03:00
|
|
|
#endif
|
2013-12-19 16:23:50 +02:00
|
|
|
size_t refs;
|
2014-10-31 23:24:23 +02:00
|
|
|
std::string libname;
|
2013-12-19 16:23:50 +02:00
|
|
|
};
|
|
|
|
internal* lib;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A program module.
|
|
|
|
*/
|
|
|
|
class module
|
|
|
|
{
|
|
|
|
template<typename T, typename... U> 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<symbol> symbols, std::function<void(const module&)> 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<typename T> T* var(const std::string& symbol) const throw(std::bad_alloc, std::runtime_error)
|
|
|
|
{
|
|
|
|
return (T*)(*this)[symbol];
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Function symbol lookup.
|
|
|
|
*/
|
|
|
|
template<typename T, typename... U> typename fntype<T, U...>::t fn(const std::string& symbol) const
|
|
|
|
throw(std::bad_alloc, std::runtime_error)
|
|
|
|
{
|
|
|
|
return (typename fntype<T, U...>::t)(*this)[symbol];
|
|
|
|
}
|
2014-10-31 23:24:23 +02:00
|
|
|
/**
|
|
|
|
* Get name.
|
|
|
|
*/
|
|
|
|
std::string get_libname() const { return libname; }
|
2013-12-19 16:23:50 +02:00
|
|
|
/**
|
|
|
|
* Run all not ran initialization functions.
|
|
|
|
*/
|
|
|
|
static void run_initializers();
|
|
|
|
private:
|
|
|
|
bool dynamic;
|
|
|
|
library lib;
|
|
|
|
std::map<std::string, void*> symbols;
|
|
|
|
std::function<void(const module&)> init;
|
2014-10-31 23:24:23 +02:00
|
|
|
std::string libname;
|
2012-10-14 23:55:36 +03:00
|
|
|
};
|
|
|
|
|
2013-12-19 16:23:50 +02:00
|
|
|
}
|
2012-10-14 23:55:36 +03:00
|
|
|
#endif
|