summaryrefslogtreecommitdiff
path: root/libmodman
diff options
context:
space:
mode:
authornpmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56>2010-02-14 00:04:12 +0000
committernpmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56>2010-02-14 00:04:12 +0000
commit79ec18bc210cb6d1823ccb51229959bcccd50af3 (patch)
treebe1919d89a15502ae3f041f0bdae9f5e829d80d2 /libmodman
parentbff77d678636923790e3c473b0c95bd5d9af6270 (diff)
downloadlibproxy-git-79ec18bc210cb6d1823ccb51229959bcccd50af3.tar.gz
rework libmodman to not use a struct in the module metadata
Diffstat (limited to 'libmodman')
-rw-r--r--libmodman/module.hpp44
-rw-r--r--libmodman/module_manager.cpp133
-rw-r--r--libmodman/module_manager.hpp1
-rw-r--r--libmodman/test/modules/module.cpp.in5
4 files changed, 95 insertions, 88 deletions
diff --git a/libmodman/module.hpp b/libmodman/module.hpp
index 39cab52..f908c00 100644
--- a/libmodman/module.hpp
+++ b/libmodman/module.hpp
@@ -24,35 +24,40 @@
#include <cstdlib>
#ifdef WIN32
-#define __MOD_DEF_PREFIX extern "C"
#define __MM_DLL_EXPORT __declspec(dllexport)
+#define __MM_FUNC_DEF_PREFIX extern "C" __MM_DLL_EXPORT
+#define __MM_SCLR_DEF_PREFIX extern "C" __MM_DLL_EXPORT
#else
-#define __MOD_DEF_PREFIX
#define __MM_DLL_EXPORT __attribute__ ((visibility("default")))
+#define __MM_FUNC_DEF_PREFIX __MM_DLL_EXPORT
+#define __MM_SCLR_DEF_PREFIX extern "C" __MM_DLL_EXPORT
#endif
#define MM_MODULE_VERSION 1
-#define MM_MODULE_NAME __module
-#define MM_MODULE_DEFINE __MOD_DEF_PREFIX struct libmodman::module __MM_DLL_EXPORT MM_MODULE_NAME[]
-#define MM_MODULE_LAST { MM_MODULE_VERSION, NULL, NULL, NULL, NULL, NULL }
-#define MM_MODULE_RECORD(type, init, test, symb, smod) \
- { MM_MODULE_VERSION, type::base_type(), init, test, symb, smod }
+#define MM_MODULE_VARNAME(name) __mm_ ## name
+#define MM_MODULE_INIT(mtype, minit) \
+ template <class T> static const char* mtype ## _type() { return T::base_type(); } \
+ __MM_SCLR_DEF_PREFIX const unsigned int MM_MODULE_VARNAME(vers) = MM_MODULE_VERSION; \
+ __MM_FUNC_DEF_PREFIX const char* (*MM_MODULE_VARNAME(type))() = mtype ## _type<mtype>; \
+ __MM_FUNC_DEF_PREFIX base_extension** (*MM_MODULE_VARNAME(init))() = minit;
+#define MM_MODULE_TEST(mtest) \
+ __MM_FUNC_DEF_PREFIX bool (*MM_MODULE_VARNAME(test))() = mtest;
+#define MM_MODULE_SYMB(msymb, msmod) \
+ __MM_SCLR_DEF_PREFIX const char* const MM_MODULE_VARNAME(symb) = msymb; \
+ __MM_SCLR_DEF_PREFIX const char* const MM_MODULE_VARNAME(smod) = msmod;
-#define MM_MODULE_EZ(clsname, cond, symb, smod) \
- static bool clsname ## _test() { \
- return (cond); \
- } \
+#define MM_MODULE_INIT_EZ(clsname) \
static libmodman::base_extension** clsname ## _init() { \
libmodman::base_extension** retval = new libmodman::base_extension*[2]; \
retval[0] = new clsname(); \
retval[1] = NULL; \
return retval; \
} \
- MM_MODULE_DEFINE = { \
- MM_MODULE_RECORD(clsname, clsname ## _init, clsname ## _test, symb, smod), \
- MM_MODULE_LAST, \
- };
+ MM_MODULE_INIT(clsname, clsname ## _init)
+#define MM_MODULE_TEST_EZ(clsname, mtest) \
+ static bool clsname ## _test() { return mtest; } \
+ MM_MODULE_TEST(clsname ## _test)
namespace libmodman {
@@ -71,15 +76,6 @@ public:
static const char* base_type() { return typeid(T).name(); }
};
-struct module {
- const unsigned int vers;
- const char* const type;
- base_extension** (*init)();
- bool (*test)();
- const char* const symb;
- const char* const smod;
-};
-
}
#endif /* MODULE_HPP_ */
diff --git a/libmodman/module_manager.cpp b/libmodman/module_manager.cpp
index 65f985d..f959105 100644
--- a/libmodman/module_manager.cpp
+++ b/libmodman/module_manager.cpp
@@ -31,6 +31,8 @@
#include "module_manager.hpp"
using namespace libmodman;
+#include <cstdio>
+
#ifdef WIN32
#define pdlmtype HMODULE
#define pdlopen(filename) LoadLibrary(filename)
@@ -67,7 +69,7 @@ static string pdlerror() {
return dlerror();
}
-static bool pdlsymlinked(const char* modn, const char* symb) {
+bool pdlsymlinked(const char* modn, const char* symb) {
void* mod = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
if (mod) {
void* sym = dlsym(mod, symb);
@@ -95,30 +97,15 @@ module_manager::~module_manager() {
pdlclose(*i);
this->modules.clear();
}
-
+/*
bool module_manager::load_module(module* mi) {
const char* debug = getenv("_MM_DEBUG");
bool loaded = false;
for (unsigned int i=0 ; mi[i].vers == MM_MODULE_VERSION && mi[i].type && mi[i].init ; i++) {
- // If our execution test succeeds, call init()
- if (mi[i].test()) {
- base_extension** extensions = mi[i].init();
- if (extensions) {
- // init() returned extensions we need to register
- loaded = true;
- for (unsigned int j=0 ; extensions[j] ; j++) {
- if (debug)
- cerr << "\tRegistering "
- << typeid(*extensions[j]).name() << "("
- << mi[i].type << ")" << endl;
- this->extensions[mi[i].type].push_back(extensions[j]);
- }
- delete extensions;
- }
- }
+
}
return loaded;
-}
+}*/
bool module_manager::load_file(string filename, bool symbreq) {
const char* debug = getenv("_MM_DEBUG");
@@ -148,68 +135,90 @@ bool module_manager::load_file(string filename, bool symbreq) {
return true;
}
- // Get the module_info struct
- module* mi = (module*) pdlsym(dlobj, __str(MM_MODULE_NAME));
- if (!mi) {
+ // Get the module info
+ const unsigned int* vers = (unsigned int*) pdlsym(dlobj, __str(MM_MODULE_VARNAME(vers)));
+ const char* const (**type)() = (const char* const (**)()) pdlsym(dlobj, __str(MM_MODULE_VARNAME(type)));
+ base_extension** (**init)() = (base_extension** (**)()) pdlsym(dlobj, __str(MM_MODULE_VARNAME(init)));
+ bool (**test)() = (bool (**)()) pdlsym(dlobj, __str(MM_MODULE_VARNAME(test)));
+ const char** const symb = (const char** const) pdlsym(dlobj, __str(MM_MODULE_VARNAME(symb)));
+ const char** const smod = (const char** const) pdlsym(dlobj, __str(MM_MODULE_VARNAME(smod)));
+ if (!vers || !type || !init || !*type || !*init || *vers != MM_MODULE_VERSION) {
if (debug)
cerr << "failed!" << endl
- << "\tUnable to find struct: " __str(MM_MODULE_NAME) << endl;
+ << "\tUnable to find basic module info!" << endl;
pdlclose(dlobj);
return false;
}
- bool tryload = false;
- for (unsigned int i=0 ; mi[i].vers == MM_MODULE_VERSION && mi[i].type && mi[i].init ; i++) {
- // Make sure the type is registered
- if (this->extensions.find(mi[i].type) == this->extensions.end()) {
+ // Make sure the type is registered
+ if (this->extensions.find((*type)()) == this->extensions.end()) {
+ if (debug)
+ cerr << "failed!" << endl
+ << "\tUnknown extension type: " << (*type)() << endl;
+ pdlclose(dlobj);
+ return false;
+ }
+
+ // If this is a singleton and we already have an instance, don't instantiate
+ if (this->singletons.find((*type)()) != this->singletons.end() &&
+ this->extensions[(*type)()].size() > 0) {
+ if (debug)
+ cerr << "failed!" << endl
+ << "\tNot loading subsequent singleton for: " << (*type)() << endl;
+ pdlclose(dlobj);
+ return false;
+ }
+
+ // If a symbol is defined, we'll search for it in the main process
+ if (symb && *symb && smod && *smod && !pdlsymlinked(*smod, *symb)) {
+ // If the symbol is not found and the symbol is required, error
+ if (symbreq) {
if (debug)
cerr << "failed!" << endl
- << "\tUnknown extension type: " << mi[i].type << endl;
- continue;
+ << "\tUnable to find required symbol: "
+ << symb << endl;
+ pdlclose(dlobj);
+ return false;
}
- // If this is a singleton and we already have an instance, don't instantiate
- if (this->singletons.find(mi[i].type) != this->singletons.end() &&
- this->extensions[mi[i].type].size() > 0) {
+ // If the symbol is not found and not required, we'll load only
+ // if there are no other modules of this type
+ else if (this->extensions[(*type)()].size() > 0) {
if (debug)
cerr << "failed!" << endl
- << "\tNot loading subsequent singleton for: " << mi[i].type << endl;
- continue;
+ << "\tUnable to find required symbol: "
+ << symb << endl;
+ pdlclose(dlobj);
+ return false;
}
+ }
- // If a symbol is defined, we'll search for it in the main process
- if (mi[i].symb) {
- // Try to find the symbol in the main process
- if (!pdlsymlinked(mi[i].smod, mi[i].symb)) {
- // If the symbol is not found and the symbol is required, continue
- // If the symbol is not found and not required, we'll load only
- // if there are no other modules of this type
- if (symbreq || this->extensions[mi[i].type].size() > 0) {
- if (debug)
- cerr << "failed!" << endl
- << "\tUnable to find required symbol: "
- << mi[i].symb << endl;
- continue;
- }
- }
+ // If our execution test succeeds, call init()
+ if ((test && *test && (*test)()) || !test || !*test) {
+ base_extension** extensions = (*init)();
+ if (!extensions) {
+ pdlclose(dlobj);
+ return false;
}
- tryload = true;
- }
-
- // Our tests failed
- if (debug) cerr << endl;
- if (!tryload) {
if (debug)
- cerr << "\tNo suitable extension factories to try!" << endl;
- pdlclose(dlobj);
- return false;
- }
+ cerr << "success" << endl;
- // We didn't load this module, so exit
- if (!this->load_module(mi)) {
+ // init() returned extensions we need to register
+ for (unsigned int i=0 ; extensions[i] ; i++) {
+ if (debug)
+ cerr << "\tRegistering "
+ << typeid(*extensions[i]).name() << "("
+ << (*type)() << ")" << endl;
+ this->extensions[(*type)()].push_back(extensions[i]);
+ }
+ delete extensions;
+ }
+ else {
if (debug)
- cerr << "\tAll extension factories failed!" << endl;
+ cerr << "failed!" << endl
+ << "\tTest execution failed: "
+ << symb << endl;
pdlclose(dlobj);
return false;
}
diff --git a/libmodman/module_manager.hpp b/libmodman/module_manager.hpp
index 9df4285..36bab5d 100644
--- a/libmodman/module_manager.hpp
+++ b/libmodman/module_manager.hpp
@@ -42,7 +42,6 @@ using namespace std;
class __MM_DLL_EXPORT module_manager {
public:
~module_manager();
- bool load_module(module* module);
bool load_file(string filename, bool symbreq=true);
bool load_dir(string dirname, bool symbreq=true, string suffix=_MOD_SUFFIX);
diff --git a/libmodman/test/modules/module.cpp.in b/libmodman/test/modules/module.cpp.in
index 41ccd25..cefe24a 100644
--- a/libmodman/test/modules/module.cpp.in
+++ b/libmodman/test/modules/module.cpp.in
@@ -21,4 +21,7 @@
#include <libmodman/module.hpp>
class @MODNAME@ : public @MODTYPE@_extension {};
-MM_MODULE_EZ(@MODNAME@, @MODCOND@, @MODSYMB@, @MODSMOD@);
+bool test() { return @MODCOND@; }
+MM_MODULE_INIT_EZ(@MODNAME@);
+MM_MODULE_TEST(test);
+MM_MODULE_SYMB(@MODSYMB@, @MODSMOD@);