|
||||
File indexing completed on 2025-01-18 09:30:45
0001 // Copyright 2016 Klemens Morgenstern 0002 // Copyright Antony Polukhin, 2019-2023 0003 // 0004 // Distributed under the Boost Software License, Version 1.0. 0005 // (See accompanying file LICENSE_1_0.txt 0006 // or copy at http://www.boost.org/LICENSE_1_0.txt) 0007 0008 #ifndef BOOST_DLL_SMART_LIBRARY_HPP_ 0009 #define BOOST_DLL_SMART_LIBRARY_HPP_ 0010 0011 /// \file boost/dll/smart_library.hpp 0012 /// \warning Extremely experimental! Requires C++11! Will change in next version of Boost! boost/dll/smart_library.hpp is not included in boost/dll.hpp 0013 /// \brief Contains the boost::dll::experimental::smart_library class for loading mangled symbols. 0014 0015 #include <boost/dll/config.hpp> 0016 #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows 0017 # include <boost/dll/detail/demangling/msvc.hpp> 0018 #else 0019 # include <boost/dll/detail/demangling/itanium.hpp> 0020 #endif 0021 0022 #if (__cplusplus < 201103L) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201103L) 0023 # error This file requires C++11 at least! 0024 #endif 0025 0026 #include <boost/dll/shared_library.hpp> 0027 #include <boost/dll/detail/get_mem_fn_type.hpp> 0028 #include <boost/dll/detail/ctor_dtor.hpp> 0029 #include <boost/dll/detail/type_info.hpp> 0030 #include <boost/type_traits/is_object.hpp> 0031 #include <boost/type_traits/is_void.hpp> 0032 #include <boost/type_traits/is_function.hpp> 0033 0034 0035 0036 namespace boost { 0037 namespace dll { 0038 namespace experimental { 0039 0040 using boost::dll::detail::constructor; 0041 using boost::dll::detail::destructor; 0042 0043 /*! 0044 * \brief This class is an extension of \ref shared_library, which allows to load C++ symbols. 0045 * 0046 * This class allows type safe loading of overloaded functions, member-functions, constructors and variables. 0047 * It also allows to overwrite classes so they can be loaded, while being declared with different names. 0048 * 0049 * \warning Is still very experimental. 0050 * 0051 * Currently known limitations: 0052 * 0053 * Member functions must be defined outside of the class to be exported. That is: 0054 * \code 0055 * //not exported: 0056 * struct BOOST_SYMBOL_EXPORT my_class { void func() {}}; 0057 * //exported 0058 * struct BOOST_SYMBOL_EXPORT my_class { void func();}; 0059 * void my_class::func() {}; 0060 * \endcode 0061 * 0062 * With the current analysis, the first version does get exported in MSVC. 0063 * MinGW also does export it, BOOST_SYMBOL_EXPORT is written before it. To allow this on windows one can use 0064 * BOOST_DLL_MEMBER_EXPORT for this, so that MinGW and MSVC can provide those functions. This does however not work with gcc on linux. 0065 * 0066 * Direct initialization of members. 0067 * On linux the following member variable i will not be initialized when using the allocating constructor: 0068 * \code 0069 * struct BOOST_SYMBOL_EXPORT my_class { int i; my_class() : i(42) {} }; 0070 * \endcode 0071 * 0072 * This does however not happen when the value is set inside the constructor function. 0073 */ 0074 class smart_library { 0075 shared_library _lib; 0076 detail::mangled_storage_impl _storage; 0077 0078 public: 0079 /*! 0080 * Get the underlying shared_library 0081 */ 0082 const shared_library &shared_lib() const {return _lib;} 0083 0084 using mangled_storage = detail::mangled_storage_impl; 0085 /*! 0086 * Access to the mangled storage, which is created on construction. 0087 * 0088 * \throw Nothing. 0089 */ 0090 const mangled_storage &symbol_storage() const {return _storage;} 0091 0092 ///Overload, for current development. 0093 mangled_storage &symbol_storage() {return _storage;} 0094 0095 //! \copydoc shared_library::shared_library() 0096 smart_library() BOOST_NOEXCEPT {}; 0097 0098 //! \copydoc shared_library::shared_library(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) 0099 smart_library(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) { 0100 _lib.load(lib_path, mode); 0101 _storage.load(lib_path); 0102 } 0103 0104 //! \copydoc shared_library::shared_library(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) 0105 smart_library(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) { 0106 load(lib_path, mode, ec); 0107 } 0108 0109 //! \copydoc shared_library::shared_library(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) 0110 smart_library(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) { 0111 load(lib_path, mode, ec); 0112 } 0113 /*! 0114 * copy a smart_library object. 0115 * 0116 * \param lib A smart_library to move from. 0117 * 0118 * \throw Nothing. 0119 */ 0120 smart_library(const smart_library & lib) BOOST_NOEXCEPT 0121 : _lib(lib._lib), _storage(lib._storage) 0122 {} 0123 /*! 0124 * Move a smart_library object. 0125 * 0126 * \param lib A smart_library to move from. 0127 * 0128 * \throw Nothing. 0129 */ 0130 smart_library(BOOST_RV_REF(smart_library) lib) BOOST_NOEXCEPT 0131 : _lib(boost::move(lib._lib)), _storage(boost::move(lib._storage)) 0132 {} 0133 0134 /*! 0135 * Construct from a shared_library object. 0136 * 0137 * \param lib A shared_library to move from. 0138 * 0139 * \throw Nothing. 0140 */ 0141 explicit smart_library(const shared_library & lib) BOOST_NOEXCEPT 0142 : _lib(lib) 0143 { 0144 _storage.load(lib.location()); 0145 } 0146 /*! 0147 * Construct from a shared_library object. 0148 * 0149 * \param lib A shared_library to move from. 0150 * 0151 * \throw Nothing. 0152 */ 0153 explicit smart_library(BOOST_RV_REF(shared_library) lib) BOOST_NOEXCEPT 0154 : _lib(boost::move(static_cast<shared_library&>(lib))) 0155 { 0156 _storage.load(lib.location()); 0157 } 0158 0159 /*! 0160 * Destroys the smart_library. 0161 * `unload()` is called if the DLL/DSO was loaded. If library was loaded multiple times 0162 * by different instances of shared_library, the actual DLL/DSO won't be unloaded until 0163 * there is at least one instance of shared_library. 0164 * 0165 * \throw Nothing. 0166 */ 0167 ~smart_library() BOOST_NOEXCEPT {}; 0168 0169 //! \copydoc shared_library::load(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) 0170 void load(const boost::dll::fs::path& lib_path, load_mode::type mode = load_mode::default_mode) { 0171 boost::dll::fs::error_code ec; 0172 _storage.load(lib_path); 0173 _lib.load(lib_path, mode, ec); 0174 0175 if (ec) { 0176 boost::dll::detail::report_error(ec, "load() failed"); 0177 } 0178 } 0179 0180 //! \copydoc shared_library::load(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) 0181 void load(const boost::dll::fs::path& lib_path, boost::dll::fs::error_code& ec, load_mode::type mode = load_mode::default_mode) { 0182 ec.clear(); 0183 _storage.load(lib_path); 0184 _lib.load(lib_path, mode, ec); 0185 } 0186 0187 //! \copydoc shared_library::load(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) 0188 void load(const boost::dll::fs::path& lib_path, load_mode::type mode, boost::dll::fs::error_code& ec) { 0189 ec.clear(); 0190 _storage.load(lib_path); 0191 _lib.load(lib_path, mode, ec); 0192 } 0193 0194 /*! 0195 * Load a variable from the referenced library. 0196 * 0197 * Unlinke shared_library::get this function will also load scoped variables, which also includes static class members. 0198 * 0199 * \note When mangled, MSVC will also check the type. 0200 * 0201 * \param name Name of the variable 0202 * \tparam T Type of the variable 0203 * \return A reference to the variable of type T. 0204 * 0205 * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. 0206 */ 0207 template<typename T> 0208 T& get_variable(const std::string &name) const { 0209 return _lib.get<T>(_storage.get_variable<T>(name)); 0210 } 0211 0212 /*! 0213 * Load a function from the referenced library. 0214 * 0215 * \b Example: 0216 * 0217 * \code 0218 * smart_library lib("test_lib.so"); 0219 * typedef int (&add_ints)(int, int); 0220 * typedef double (&add_doubles)(double, double); 0221 * add_ints f1 = lib.get_function<int(int, int)> ("func_name"); 0222 * add_doubles f2 = lib.get_function<double(double, double)>("func_name"); 0223 * \endcode 0224 * 0225 * \note When mangled, MSVC will also check the return type. 0226 * 0227 * \param name Name of the function. 0228 * \tparam Func Type of the function, required for determining the overload 0229 * \return A reference to the function of type F. 0230 * 0231 * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. 0232 */ 0233 template<typename Func> 0234 Func& get_function(const std::string &name) const { 0235 return _lib.get<Func>(_storage.get_function<Func>(name)); 0236 } 0237 0238 /*! 0239 * Load a member-function from the referenced library. 0240 * 0241 * \b Example (import class is MyClass, which is available inside the library and the host): 0242 * 0243 * \code 0244 * smart_library lib("test_lib.so"); 0245 * 0246 * typedef int MyClass(*func)(int); 0247 * typedef int MyClass(*func_const)(int) const; 0248 * 0249 * add_ints f1 = lib.get_mem_fn<MyClass, int(int)> ("MyClass::function"); 0250 * add_doubles f2 = lib.get_mem_fn<const MyClass, double(double)>("MyClass::function"); 0251 * \endcode 0252 * 0253 * \note When mangled, MSVC will also check the return type. 0254 * 0255 * \param name Name of the function. 0256 * \tparam Class The class the function is a member of. If Class is const, the function will be assumed as taking a const this-pointer. The same applies for volatile. 0257 * \tparam Func Signature of the function, required for determining the overload 0258 * \return A pointer to the member-function with the signature provided 0259 * 0260 * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. 0261 */ 0262 template<typename Class, typename Func> 0263 typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn get_mem_fn(const std::string& name) const { 0264 return _lib.get<typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn>( 0265 _storage.get_mem_fn<Class, Func>(name) 0266 ); 0267 } 0268 0269 /*! 0270 * Load a constructor from the referenced library. 0271 * 0272 * \b Example (import class is MyClass, which is available inside the library and the host): 0273 * 0274 * \code 0275 * smart_library lib("test_lib.so"); 0276 * 0277 * constructor<MyClass(int) f1 = lib.get_mem_fn<MyClass(int)>(); 0278 * \endcode 0279 * 0280 * \tparam Signature Signature of the function, required for determining the overload. The return type is the class which this is the constructor of. 0281 * \return A constructor object. 0282 * 0283 * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. 0284 */ 0285 template<typename Signature> 0286 constructor<Signature> get_constructor() const { 0287 return boost::dll::detail::load_ctor<Signature>(_lib, _storage.get_constructor<Signature>()); 0288 } 0289 0290 /*! 0291 * Load a destructor from the referenced library. 0292 * 0293 * \b Example (import class is MyClass, which is available inside the library and the host): 0294 * 0295 * \code 0296 * smart_library lib("test_lib.so"); 0297 * 0298 * destructor<MyClass> f1 = lib.get_mem_fn<MyClass>(); 0299 * \endcode 0300 * 0301 * \tparam Class The class whose destructor shall be loaded 0302 * \return A destructor object. 0303 * 0304 * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. 0305 * 0306 */ 0307 template<typename Class> 0308 destructor<Class> get_destructor() const { 0309 return boost::dll::detail::load_dtor<Class>(_lib, _storage.get_destructor<Class>()); 0310 } 0311 /*! 0312 * Load the typeinfo of the given type. 0313 * 0314 * \b Example (import class is MyClass, which is available inside the library and the host): 0315 * 0316 * \code 0317 * smart_library lib("test_lib.so"); 0318 * 0319 * std::type_info &ti = lib.get_Type_info<MyClass>(); 0320 * \endcode 0321 * 0322 * \tparam Class The class whose typeinfo shall be loaded 0323 * \return A reference to a type_info object. 0324 * 0325 * \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded. 0326 * 0327 */ 0328 template<typename Class> 0329 const std::type_info& get_type_info() const 0330 { 0331 return boost::dll::detail::load_type_info<Class>(_lib, _storage); 0332 } 0333 /** 0334 * This function can be used to add a type alias. 0335 * 0336 * This is to be used, when a class shall be imported, which is not declared on the host side. 0337 * 0338 * Example: 0339 * \code 0340 * smart_library lib("test_lib.so"); 0341 * 0342 * lib.add_type_alias<MyAlias>("MyClass"); //when using MyAlias, the library will look for MyClass 0343 * 0344 * //get the destructor of MyClass 0345 * destructor<MyAlias> dtor = lib.get_destructor<MyAlias>(); 0346 * \endcode 0347 * 0348 * 0349 * \param name Name of the class the alias is for. 0350 * 0351 * \attention If the alias-type is not large enough for the imported class, it will result in undefined behaviour. 0352 * \warning The alias will only be applied for the type signature, it will not replace the token in the scoped name. 0353 */ 0354 template<typename Alias> void add_type_alias(const std::string& name) { 0355 this->_storage.add_alias<Alias>(name); 0356 } 0357 0358 //! \copydoc shared_library::unload() 0359 void unload() BOOST_NOEXCEPT { 0360 _storage.clear(); 0361 _lib.unload(); 0362 } 0363 0364 //! \copydoc shared_library::is_loaded() const 0365 bool is_loaded() const BOOST_NOEXCEPT { 0366 return _lib.is_loaded(); 0367 } 0368 0369 //! \copydoc shared_library::operator!() const 0370 bool operator!() const BOOST_NOEXCEPT { 0371 return !is_loaded(); 0372 } 0373 0374 //! \copydoc shared_library::operator bool() const 0375 BOOST_EXPLICIT_OPERATOR_BOOL() 0376 0377 //! \copydoc shared_library::has(const char* symbol_name) const 0378 bool has(const char* symbol_name) const BOOST_NOEXCEPT { 0379 return _lib.has(symbol_name); 0380 } 0381 0382 //! \copydoc shared_library::has(const std::string& symbol_name) const 0383 bool has(const std::string& symbol_name) const BOOST_NOEXCEPT { 0384 return _lib.has(symbol_name); 0385 } 0386 0387 //! \copydoc shared_library::assign(const shared_library& lib) 0388 smart_library& assign(const smart_library& lib) { 0389 _lib.assign(lib._lib); 0390 _storage.assign(lib._storage); 0391 return *this; 0392 } 0393 0394 //! \copydoc shared_library::swap(shared_library& rhs) 0395 void swap(smart_library& rhs) BOOST_NOEXCEPT { 0396 _lib.swap(rhs._lib); 0397 _storage.swap(rhs._storage); 0398 } 0399 }; 0400 0401 /// Very fast equality check that compares the actual DLL/DSO objects. Throws nothing. 0402 inline bool operator==(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT { 0403 return lhs.shared_lib().native() == rhs.shared_lib().native(); 0404 } 0405 0406 /// Very fast inequality check that compares the actual DLL/DSO objects. Throws nothing. 0407 inline bool operator!=(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT { 0408 return lhs.shared_lib().native() != rhs.shared_lib().native(); 0409 } 0410 0411 /// Compare the actual DLL/DSO objects without any guarantee to be stable between runs. Throws nothing. 0412 inline bool operator<(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT { 0413 return lhs.shared_lib().native() < rhs.shared_lib().native(); 0414 } 0415 0416 /// Swaps two shared libraries. Does not invalidate symbols and functions loaded from libraries. Throws nothing. 0417 inline void swap(smart_library& lhs, smart_library& rhs) BOOST_NOEXCEPT { 0418 lhs.swap(rhs); 0419 } 0420 0421 0422 #ifdef BOOST_DLL_DOXYGEN 0423 /** Helper functions for overloads. 0424 * 0425 * Gets either a variable, function or member-function, depending on the signature. 0426 * 0427 * @code 0428 * smart_library sm("lib.so"); 0429 * get<int>(sm, "space::value"); //import a variable 0430 * get<void(int)>(sm, "space::func"); //import a function 0431 * get<some_class, void(int)>(sm, "space::class_::mem_fn"); //import a member function 0432 * @endcode 0433 * 0434 * @param sm A reference to the @ref smart_library 0435 * @param name The name of the entity to import 0436 */ 0437 template<class T, class T2> 0438 void get(const smart_library& sm, const std::string &name); 0439 #endif 0440 0441 template<class T> 0442 typename boost::enable_if<boost::is_object<T>, T&>::type get(const smart_library& sm, const std::string &name) 0443 0444 { 0445 return sm.get_variable<T>(name); 0446 } 0447 0448 template<class T> 0449 typename boost::enable_if<boost::is_function<T>, T&>::type get(const smart_library& sm, const std::string &name) 0450 { 0451 return sm.get_function<T>(name); 0452 } 0453 0454 template<class Class, class Signature> 0455 auto get(const smart_library& sm, const std::string &name) -> typename detail::get_mem_fn_type<Class, Signature>::mem_fn 0456 { 0457 return sm.get_mem_fn<Class, Signature>(name); 0458 } 0459 0460 0461 } /* namespace experimental */ 0462 } /* namespace dll */ 0463 } /* namespace boost */ 0464 0465 #endif /* BOOST_DLL_SMART_LIBRARY_HPP_ */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |