Last active
November 8, 2017 16:51
-
-
Save jpclipffel/1d23f6ad338877a0fdf3 to your computer and use it in GitHub Desktop.
C++ module and module loader example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Example of an C++ module (== dynamic library which exports an object). | |
* cpp_imod.hh: Module interface; | |
* cpp_module.hh: Module implementation header; | |
* cpp_module.cpp: Module implementation source; | |
* cpp_modloader-dlfcn.cpp: Load and call module. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* C++ module example - module interface | |
* Define and implement module interface. | |
*/ | |
#ifndef IMOD_HH | |
#define IMOD_HH | |
/** | |
* Module interface. | |
* All modules must inherit from this interface. | |
* Rules: | |
* - must implement constructor | |
* - must implement destructor | |
* - other methods must be virtual pure | |
*/ | |
struct imod | |
{ | |
imod(){}; | |
virtual ~imod(){}; | |
virtual void foo() = 0; | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* C++ module example - loader implementation | |
* Load a test module. | |
*/ | |
#include <iostream> | |
#include <dlfcn.h> | |
#include "cpp_imod.hh" | |
using namespace std; | |
/** | |
* Load a module (an object from a .so file) and call a method from | |
* this module. | |
* Compilation: g++ <cpp-modloader-dlfcn.cpp> -ldl -o cpp-modloader-dlfcn | |
*/ | |
int main(int ac, char **av) | |
{ | |
void *libfd; // Library handler | |
imod *module; // Module instamce (pointer) | |
imod *(*builder)(); // Module factory | |
void (*destroyer)(imod*); // Module destructor function | |
// Test arguments | |
if (ac < 2) | |
{ | |
cerr << "usage: modloader <module.so>" << endl; | |
return 1; | |
} | |
// Clear all previous errors | |
dlerror(); | |
// Open library | |
libfd = dlopen(av[1], RTLD_LAZY); | |
// Library pointer is NULL: error | |
if (!libfd) | |
{ | |
// dlerror() return last error string | |
cerr << "dlopen(): " << dlerror() << endl; | |
return 1; | |
} | |
/** | |
* Get module factory symbol. | |
* | |
* dlsym() can return NULL (see man); however, in our case, the builder | |
* function should not be NULL. | |
* The correct (generic) way to find if error happens is to: | |
* - call dlerror() | |
* - call dlsym() | |
* - call dlerror() once again, store the result and check if it contains | |
* an error. | |
*/ | |
builder = (imod *(*)())dlsym(libfd, "build"); | |
if (!builder) | |
{ | |
cerr << "dlsym(): " << dlerror() << endl; | |
dlclose(libfd); | |
return 1; | |
} | |
/** | |
* Get module destructor symbol. | |
* Same remark as before. | |
*/ | |
destroyer = (void (*)(imod*))dlsym(libfd, "destroy"); | |
if (!destroyer) | |
{ | |
cerr << "dlsym(): " << dlerror() << endl; | |
dlclose(libfd); | |
return 1; | |
} | |
// Create a new module instance | |
module = builder(); | |
// Check if module have been created | |
if (!module) | |
{ | |
cerr << "builder(): return NULL instead of a new module" << endl; | |
dlclose(libfd); | |
return 1; | |
} | |
// Call module method(s) | |
module->foo(); | |
// Delete module | |
destroyer(module); | |
// Don't forget to close the library | |
dlclose(libfd); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* C++ module example - module implementation | |
* Implement test module. | |
*/ | |
#include "cpp_module.hh" | |
module::module() | |
{ | |
} | |
module::~module() | |
{ | |
cout << "module::~module()" << endl; | |
} | |
void module::foo() | |
{ | |
cout << "module::foo()" << endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* C++ module example - module header | |
* Define module header. | |
*/ | |
#ifndef MODULE_HH | |
#define MODULE_HH | |
#include <iostream> | |
#include "cpp_imod.hh" | |
using namespace std; | |
/** | |
* Module (implementation) header. | |
* It MUST: | |
* - inherit from interface (imod.hh) | |
* - defines the constructor and destructor | |
* - defines interface methods as virtual | |
*/ | |
struct module: public imod | |
{ | |
module(); | |
~module(); | |
virtual void foo(); | |
}; | |
/** | |
* Module factory. | |
* Since dlsym() except C mangled functions, we need to specify our | |
* factory mangling. | |
*/ | |
extern "C" imod *build() | |
{ | |
return new module; | |
} | |
/** | |
* Module destructor. | |
* Same remark as before. | |
*/ | |
extern "C" void destroy(imod *_self) | |
{ | |
if (_self) | |
delete _self; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment