$search
00001 // Copyright Vladimir Prus 2004. 00002 // Distributed under the Boost Software License, Version 1.0. 00003 // (See accompanying file LICENSE_1_0.txt 00004 // or copy at http://www.boost.org/LICENSE_1_0.txt) 00005 00006 #ifndef BOOST_DLL_HPP_VP_2004_08_24 00007 #define BOOST_DLL_HPP_VP_2004_08_24 00008 00009 #include <string> 00010 #include <stdexcept> 00011 #include <boost/shared_ptr.hpp> 00012 #include <boost/bind.hpp> 00013 #include <boost/type_traits/remove_pointer.hpp> 00014 00015 // FIXME: that's for Linux only 00016 #include <dlfcn.h> 00017 00018 #include <iostream> 00019 00020 namespace utilmm { namespace plugin { 00021 00022 struct killer 00023 { 00024 killer(void* h) : h(h) {} 00025 template<class T> 00026 void operator()(T) 00027 { 00028 std::cout << "Killing DLL\n"; 00029 dlclose(h); 00030 } 00031 void* h; 00032 }; 00033 00034 class dll { 00035 public: 00036 dll() {} // TODO: should remove this or make non-public 00037 dll(const std::string& name) : m_name(name) {} 00038 00039 template<typename SymbolType> 00040 boost::shared_ptr< 00041 typename boost::remove_pointer<SymbolType>::type> 00042 get(const std::string& symbol_name) const 00043 { 00044 // TODO: static assert that SymbolType is a pointer. 00045 typedef typename boost::remove_pointer<SymbolType>::type PointedType; 00046 00047 // Open the library. Yes, we do it on every access to 00048 // a symbol, see the design discussion in the documentation. 00049 void* handle = dlopen(m_name.c_str(), RTLD_LAZY|RTLD_GLOBAL); 00050 if (!handle) { 00051 throw std::logic_error("Could not open DLL"); 00052 } 00053 // Clear the error state. 00054 dlerror(); 00055 void* address = dlsym(handle, symbol_name.c_str()); 00056 char* error = dlerror(); 00057 if (error) { 00058 throw std::logic_error(error); 00059 } 00060 // Cast the to right type. 00061 SymbolType s = (SymbolType)(address); 00062 00063 boost::shared_ptr<PointedType> result(s, 00064 //killer(handle)); 00065 boost::bind(dlclose, handle)); 00066 00067 return result; 00068 } 00069 00070 private: 00071 std::string m_name; 00072 }; 00073 00074 }} 00075 00076 #endif