Oops from previous commit
[lsnes.git] / include / library / loadlib.hpp
blob3ea16867e4be714f45aef4e77697b659143b70a5
1 #ifndef _library__loadlib__hpp__included__
2 #define _library__loadlib__hpp__included__
4 #include <string>
5 #include <stdexcept>
6 #include <map>
7 #include "threads.hpp"
9 #if defined(_WIN32) || defined(_WIN64)
10 #include <windows.h>
11 #endif
13 namespace loadlib
15 threads::lock& global_mutex();
17 /**
18 * A loaded library.
20 class library
22 public:
23 /**
24 * Construct a NULL library.
26 library()
28 lib = NULL;
30 /**
31 * Load a new library.
33 * Parameter filename: The name of file.
34 * Throws std::bad_alloc: Not enough memory.
35 * Throws std::runtime_error: Error loading shared library.
37 library(const std::string& filename) throw(std::bad_alloc, std::runtime_error)
39 lib = new internal(filename);
41 /**
42 * Unload a library.
44 ~library() throw()
46 threads::alock h(global_mutex());
47 if(lib && !--lib->refs)
48 delete lib;
50 /**
51 * Look up a symbol.
53 * Parameter symbol: The symbol to look up.
54 * Returns: The symbol value.
55 * Throws std::bad_alloc: Not enough memory.
56 * Throws std::runtime_error: Error looking up the symbol.
58 void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error)
60 threads::alock h(global_mutex());
61 if(!lib) throw std::runtime_error("Symbol '" + symbol + "' not found");
62 return (*lib)[symbol];
64 /**
65 * See what libraries are called on this platform.
67 * Returns: The name of library.
69 static const std::string& name() throw();
70 /**
71 * See what standard library extension is on this platform.
73 * Returns: The extension of library.
75 static const std::string& extension() throw();
76 /**
77 * Copy ctor.
79 library(const library& r)
81 threads::alock h(global_mutex());
82 lib = r.lib;
83 if(lib) ++lib->refs;
85 library& operator=(const library& r)
87 if(lib == r.lib)
88 return *this;
89 threads::alock h(global_mutex());
90 if(lib && !--lib->refs)
91 delete lib;
92 lib = r.lib;
93 if(lib) ++lib->refs;
94 return *this;
96 std::string get_libname() const { return lib->libname; }
97 private:
98 struct internal
100 internal(const std::string& filename) throw(std::bad_alloc, std::runtime_error);
101 ~internal() throw();
102 void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error);
103 internal(const internal&);
104 internal& operator=(const internal&);
105 #if defined(_WIN32) || defined(_WIN64)
106 HMODULE handle;
107 #elif !defined(NO_DLFCN)
108 void* handle;
109 #endif
110 size_t refs;
111 std::string libname;
113 internal* lib;
117 * A program module.
119 class module
121 template<typename T, typename... U> struct fntype { typedef T(*t)(U...); };
122 public:
124 * Symbol definition.
126 struct symbol
128 const char* name;
129 void* address;
132 * Construct a module from list of symbols.
134 module(std::initializer_list<symbol> symbols, std::function<void(const module&)> init_fn);
136 * Construct a module from library.
138 module(library lib);
140 * Copy ctor
142 module(const module& mod);
144 * Dtor.
146 ~module();
148 * Symbol lookup.
150 void* operator[](const std::string& symbol) const throw(std::bad_alloc, std::runtime_error);
152 * Variable symbol lookup.
154 template<typename T> T* var(const std::string& symbol) const throw(std::bad_alloc, std::runtime_error)
156 return (T*)(*this)[symbol];
159 * Function symbol lookup.
161 template<typename T, typename... U> typename fntype<T, U...>::t fn(const std::string& symbol) const
162 throw(std::bad_alloc, std::runtime_error)
164 return (typename fntype<T, U...>::t)(*this)[symbol];
167 * Get name.
169 std::string get_libname() const { return libname; }
171 * Run all not ran initialization functions.
173 static void run_initializers();
174 private:
175 bool dynamic;
176 library lib;
177 std::map<std::string, void*> symbols;
178 std::function<void(const module&)> init;
179 std::string libname;
183 #endif