diff --git a/mrw/dynamiclibrary.hpp b/mrw/dynamiclibrary.hpp new file mode 100644 index 0000000..6cec2b5 --- /dev/null +++ b/mrw/dynamiclibrary.hpp @@ -0,0 +1,166 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.1 2005/02/18 15:53:56 marc + initial release + + + 1 2 3 4 5 6 7 8 + 5678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ + +#ifndef __MRW_DYNAMICLIBRARY_HPP__ +#define __MRW_DYNAMICLIBRARY_HPP__ + +#include +#include +#include +#include + +namespace mrw { + + class DynamicLibrary { + public: + class failure: public mrw::runtime_error { + public: + failure(const std::string& arg) throw(std::bad_exception): + mrw::runtime_error("DynamicLibrary failure "+arg + +"; ltdl reason: "+ + +mrw::ifelse(lt_dlerror(), "")) { + } + }; + class Lib { + Lib() throw(): _lib(0) {} + Lib(const std::string& lib) throw(std::exception): _lib(0) { + open(lib); + } + ~Lib() throw() { + try {close();} catch(...) {} + } + operator bool() throw() { + return _lib; + } + Lib& open(const std::string& lib) throw(std::exception) { + close(); + if (!(_lib = lt_dlopenext(lib.c_str()))) + throw failure("cannot open dynamic library "+lib); + return *this; + } + Lib& close() throw(std::exception) { + if (_lib && lt_dlclose(_lib)!=0) + throw failure("cannot close dynamic library"); + _lib = 0; + return *this; + } + private: + friend class DynamicLibrary; + lt_dlhandle handle() throw(std::exception) { + if (!_lib) + throw failure("library not open"); + return _lib; + } + private: + lt_dlhandle _lib; + }; + public: + DynamicLibrary() throw(std::exception): _opened(false) { + if (lt_dlinit()>0) + throw failure("cannot initialize dynamic library loader"); + _opened = true; + } + DynamicLibrary(const std::string& lib) throw(std::exception): + _opened(false) { + if (lt_dlinit()>0) + throw failure("cannot initialize dynamic library loader"); + _opened = true; + _lib.open(lib); + } + ~DynamicLibrary() throw() { + try {close();} catch (...) {} + if (_opened) lt_dlexit(); + } + DynamicLibrary& open(const std::string& lib) throw(std::exception) { + _lib.open(lib); + return *this; + } + DynamicLibrary& close() throw(std::exception) { + _lib.close(); + return *this; + } + DynamicLibrary& resident() throw(std::exception) { + if (lt_dlmakeresident(_lib.handle())!=0) + throw failure("cannot make library resident"); + return *this; + } + bool isResident() throw(std::exception) { + return lt_dlisresident(_lib.handle())==1; + } + lt_ptr symbol(const std::string& name) throw(std::exception) { + lt_ptr sym(lt_dlsym(_lib.handle(), name.c_str())); + if (!sym) + throw failure("cannot load dynamic library symbol: "+name); + return sym; + } + /** + {{"name1", &name1}, {"name2", &name2}, 0} + */ + DynamicLibrary& preload(const lt_dlsymlist* symbols) + throw(std::exception) { + if (lt_dlpreload(symbols)!=0) + throw failure("error in preloading libraries"); + return *this; + } + /** + {{"name1", &name1}, {"name2", &name2}, 0} + */ + DynamicLibrary& preloadDefault(const lt_dlsymlist* symbols) + throw(std::exception) { + if (lt_dlpreload_default(symbols)!=0) + throw failure("error in preloading libraries"); + return *this; + } + int foreachfile(const char* searchPath, + int(*function)(const char*, lt_ptr), + lt_ptr data) throw() { + return lt_dlforeachfile(searchPath, function, data); + } + /// @todo enable +// static void preloadedSymbols(const std::string& lib, +// const lt_dlsymlist symbols[]) +// throw(std::exception) { +// Lib lib(lt_dlopenext(lib.c_str())); +// LTDL_SET_PRELOADED_SYMBOLS(symbols); +// } + static void addSearchDir(const std::string& dir) throw(std::exception) { + if (lt_dladdsearchdir(dir.c_str())!=0) + throw failure("cannot add search dir: "+dir); + } + static void insertSearchDir(const std::string& before, + const std::string& dir) + throw(std::exception) { + if (lt_dlinsertsearchdir(before.c_str(), dir.c_str())!=0) + throw failure("cannot add search dir: "+dir); + } + /// @todo enable +// static std::string void setSearchPath(const std::string& dir) throw() { +// char const * const path(lt_dlgetsearchpath()); +// if (!path) +// throw failure("cannot get search path"); +// return path; +// } + private: + bool _opened; + Lib _lib; + }; + +} + +#endif diff --git a/mrw/dynamiclibrary_test.cpp b/mrw/dynamiclibrary_test.cpp new file mode 100644 index 0000000..51d7b11 --- /dev/null +++ b/mrw/dynamiclibrary_test.cpp @@ -0,0 +1,47 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.1 2005/02/18 15:53:56 marc + initial release + + + 1 2 3 4 5 6 7 8 + 5678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ + +#include +#include +#include +#include +#include + +class DynamicLibraryTest: public CppUnit::TestFixture { + public: + void Load() { + mrw::DynamicLibrary lib("libdynamiclibrary_testlib"); + int(*test1)(int) = (int(*)(int))lib.symbol("test1"); + CPPUNIT_ASSERT((*test1)(2)==4); + } + void LoadError() { + mrw::DynamicLibrary lib("DASist-Sicher_Keine_DynamischePHIPLIOTEEK!!!"); + } + CPPUNIT_TEST_SUITE(DynamicLibraryTest); + CPPUNIT_TEST(Load); + CPPUNIT_TEST_EXCEPTION(LoadError, mrw::DynamicLibrary::failure); + CPPUNIT_TEST_SUITE_END(); +}; +CPPUNIT_TEST_SUITE_REGISTRATION(DynamicLibraryTest); + +int main() { + CppUnit::TextUi::TestRunner runner; + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); + return runner.run() ? 0 : 1; +} diff --git a/mrw/dynamiclibrary_testlib.cpp b/mrw/dynamiclibrary_testlib.cpp new file mode 100644 index 0000000..63479b4 --- /dev/null +++ b/mrw/dynamiclibrary_testlib.cpp @@ -0,0 +1,24 @@ +/** @file + + $Id$ + + $Date$ + $Author$ + + @copy © Marc Wäckerlin + @license LGPL, see file COPYING + + $Log$ + Revision 1.1 2005/02/18 15:53:55 marc + initial release + + + 1 2 3 4 5 6 7 8 + 5678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ + +extern "C" { + int test1(int i) { + return i*i; + } +}