]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/dll/include/boost/dll/smart_library.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / dll / include / boost / dll / smart_library.hpp
1 // Copyright 2016 Klemens Morgenstern
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef BOOST_DLL_SMART_LIBRARY_HPP_
8 #define BOOST_DLL_SMART_LIBRARY_HPP_
9
10 /// \file boost/dll/smart_library.hpp
11 /// \warning Extremely experimental! Requires C++14! Will change in next version of Boost! boost/dll/smart_library.hpp is not included in boost/dll.hpp
12 /// \brief Contains the boost::dll::experimental::smart_library class for loading mangled symbols.
13
14 #if BOOST_COMP_GNUC || BOOST_COMP_CLANG || BOOST_COMP_HPACC || BOOST_COMP_IBM
15 #include <boost/dll/detail/demangling/itanium.hpp>
16 #elif BOOST_COMP_MSVC
17 #include <boost/dll/detail/demangling/msvc.hpp>
18 #else
19 #error "Compiler not supported"
20 #endif
21
22 #include <boost/dll/shared_library.hpp>
23 #include <boost/dll/detail/get_mem_fn_type.hpp>
24 #include <boost/dll/detail/ctor_dtor.hpp>
25 #include <boost/dll/detail/type_info.hpp>
26 #include <boost/type_traits/is_object.hpp>
27 #include <boost/type_traits/is_void.hpp>
28 #include <boost/type_traits/is_function.hpp>
29 #include <boost/predef/compiler.h>
30
31
32
33 namespace boost {
34 namespace dll {
35 namespace experimental {
36
37 using boost::dll::detail::constructor;
38 using boost::dll::detail::destructor;
39
40 /*!
41 * \brief This class is an extension of \ref shared_library, which allows to load C++ symbols.
42 *
43 * This class allows type safe loading of overloaded functions, member-functions, constructors and variables.
44 * It also allows to overwrite classes so they can be loaded, while being declared with different names.
45 *
46 * \warning Is still very experimental.
47 *
48 * Currently known limitations:
49 *
50 * Member functions must be defined outside of the class to be exported. That is:
51 * \code
52 * //not exported:
53 * struct BOOST_SYMBOL_EXPORT my_class { void func() {}};
54 * //exported
55 * struct BOOST_SYMBOL_EXPORT my_class { void func();};
56 * void my_class::func() {};
57 * \endcode
58 *
59 * With the current analysis, the first version does get exported in MSVC.
60 * MinGW also does export it, BOOST_SYMBOL_EXPORT is written before it. To allow this on windows one can use
61 * BOOST_DLL_MEMBER_EXPORT for this, so that MinGW and MSVC can provide those functions. This does however not work with gcc on linux.
62 *
63 * Direct initialization of members.
64 * On linux the following member variable i will not be initialized when using the allocating contructor:
65 * \code
66 * struct BOOST_SYMBOL_EXPORT my_class { int i; my_class() : i(42) {} };
67 * \endcode
68 *
69 * This does however not happen when the value is set inside the constructor function.
70 */
71 class smart_library {
72 shared_library _lib;
73 detail::mangled_storage_impl _storage;
74
75 public:
76 /*!
77 * Get the underlying shared_library
78 */
79 const shared_library &shared_lib() const {return _lib;}
80
81 using mangled_storage = detail::mangled_storage_impl;
82 /*!
83 * Acces to the mangled storage, which is created on construction.
84 *
85 * \throw Nothing.
86 */
87 const mangled_storage &symbol_storage() const {return _storage;}
88
89 ///Overload, for current development.
90 mangled_storage &symbol_storage() {return _storage;}
91
92 //! \copydoc shared_library::shared_library()
93 smart_library() BOOST_NOEXCEPT {};
94
95 //! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode)
96 smart_library(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode) {
97 _lib.load(lib_path, mode);
98 _storage.load(lib_path, mode);
99 }
100
101 //! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode)
102 smart_library(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode) {
103 load(lib_path, mode, ec);
104 }
105
106 //! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec)
107 smart_library(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec) {
108 load(lib_path, mode, ec);
109 }
110 /*!
111 * copy a smart_library object.
112 *
113 * \param lib A smart_library to move from.
114 *
115 * \throw Nothing.
116 */
117 smart_library(const smart_library & lib) BOOST_NOEXCEPT
118 : _lib(lib._lib), _storage(lib._storage)
119 {}
120 /*!
121 * Move a smart_library object.
122 *
123 * \param lib A smart_library to move from.
124 *
125 * \throw Nothing.
126 */
127 smart_library(BOOST_RV_REF(smart_library) lib) BOOST_NOEXCEPT
128 : _lib(boost::move(lib._lib)), _storage(boost::move(lib._storage))
129 {}
130
131 /*!
132 * Construct from a shared_library object.
133 *
134 * \param lib A shared_library to move from.
135 *
136 * \throw Nothing.
137 */
138 explicit smart_library(const shared_library & lib) BOOST_NOEXCEPT
139 : _lib(lib)
140 {
141 _storage.load(lib.location());
142 }
143 /*!
144 * Construct from a shared_library object.
145 *
146 * \param lib A shared_library to move from.
147 *
148 * \throw Nothing.
149 */
150 explicit smart_library(BOOST_RV_REF(shared_library) lib) BOOST_NOEXCEPT
151 : _lib(boost::move(static_cast<shared_library&>(lib)))
152 {
153 _storage.load(lib.location());
154 }
155
156 /*!
157 * Destroys the smart_library.
158 * `unload()` is called if the DLL/DSO was loaded. If library was loaded multiple times
159 * by different instances of shared_library, the actual DLL/DSO won't be unloaded until
160 * there is at least one instance of shared_library.
161 *
162 * \throw Nothing.
163 */
164 ~smart_library() BOOST_NOEXCEPT {};
165
166 //! \copydoc shared_library::load(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode)
167 void load(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode) {
168 boost::system::error_code ec;
169 _storage.load(lib_path);
170 _lib.load(lib_path, mode, ec);
171
172 if (ec) {
173 boost::dll::detail::report_error(ec, "load() failed");
174 }
175 }
176
177 //! \copydoc shared_library::load(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode)
178 void load(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode) {
179 ec.clear();
180 _storage.load(lib_path);
181 _lib.load(lib_path, mode, ec);
182 }
183
184 //! \copydoc shared_library::load(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec)
185 void load(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec) {
186 ec.clear();
187 _storage.load(lib_path);
188 _lib.load(lib_path, mode, ec);
189 }
190
191 /*!
192 * Load a variable from the referenced library.
193 *
194 * Unlinke shared_library::get this function will also load scoped variables, which also includes static class members.
195 *
196 * \note When mangled, MSVC will also check the type.
197 *
198 * \param name Name of the variable
199 * \tparam T Type of the variable
200 * \return A reference to the variable of type T.
201 *
202 * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
203 */
204 template<typename T>
205 T& get_variable(const std::string &name) const {
206 return _lib.get<T>(_storage.get_variable<T>(name));
207 }
208
209 /*!
210 * Load a function from the referenced library.
211 *
212 * \b Example:
213 *
214 * \code
215 * smart_library lib("test_lib.so");
216 * typedef int (&add_ints)(int, int);
217 * typedef double (&add_doubles)(double, double);
218 * add_ints f1 = lib.get_function<int(int, int)> ("func_name");
219 * add_doubles f2 = lib.get_function<double(double, double)>("func_name");
220 * \endcode
221 *
222 * \note When mangled, MSVC will also check the return type.
223 *
224 * \param name Name of the function.
225 * \tparam Func Type of the function, required for determining the overload
226 * \return A reference to the function of type F.
227 *
228 * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
229 */
230 template<typename Func>
231 Func& get_function(const std::string &name) const {
232 return _lib.get<Func>(_storage.get_function<Func>(name));
233 }
234
235 /*!
236 * Load a member-function from the referenced library.
237 *
238 * \b Example (import class is MyClass, which is available inside the library and the host):
239 *
240 * \code
241 * smart_library lib("test_lib.so");
242 *
243 * typedef int MyClass(*func)(int);
244 * typedef int MyClass(*func_const)(int) const;
245 *
246 * add_ints f1 = lib.get_mem_fn<MyClass, int(int)> ("MyClass::function");
247 * add_doubles f2 = lib.get_mem_fn<const MyClass, double(double)>("MyClass::function");
248 * \endcode
249 *
250 * \note When mangled, MSVC will also check the return type.
251 *
252 * \param name Name of the function.
253 * \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.
254 * \tparam Func Signature of the function, required for determining the overload
255 * \return A pointer to the member-function with the signature provided
256 *
257 * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
258 */
259 template<typename Class, typename Func>
260 typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn get_mem_fn(const std::string& name) const {
261 return _lib.get<typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn>(
262 _storage.get_mem_fn<Class, Func>(name)
263 );
264 }
265
266 /*!
267 * Load a constructor from the referenced library.
268 *
269 * \b Example (import class is MyClass, which is available inside the library and the host):
270 *
271 * \code
272 * smart_library lib("test_lib.so");
273 *
274 * constructor<MyClass(int) f1 = lib.get_mem_fn<MyClass(int)>();
275 * \endcode
276 *
277 * \tparam Signature Signature of the function, required for determining the overload. The return type is the class which this is the constructor of.
278 * \return A constructor object.
279 *
280 * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
281 */
282 template<typename Signature>
283 constructor<Signature> get_constructor() const {
284 return boost::dll::detail::load_ctor<Signature>(_lib, _storage.get_constructor<Signature>());
285 }
286
287 /*!
288 * Load a destructor from the referenced library.
289 *
290 * \b Example (import class is MyClass, which is available inside the library and the host):
291 *
292 * \code
293 * smart_library lib("test_lib.so");
294 *
295 * destructor<MyClass> f1 = lib.get_mem_fn<MyClass>();
296 * \endcode
297 *
298 * \tparam Class The class whichs destructor shall be loaded
299 * \return A destructor object.
300 *
301 * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
302 *
303 */
304 template<typename Class>
305 destructor<Class> get_destructor() const {
306 return boost::dll::detail::load_dtor<Class>(_lib, _storage.get_destructor<Class>());
307 }
308 /*!
309 * Load the typeinfo of the given type.
310 *
311 * \b Example (import class is MyClass, which is available inside the library and the host):
312 *
313 * \code
314 * smart_library lib("test_lib.so");
315 *
316 * std::type_info &ti = lib.get_Type_info<MyClass>();
317 * \endcode
318 *
319 * \tparam Class The class whichs typeinfo shall be loaded
320 * \return A reference to a type_info object.
321 *
322 * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
323 *
324 */
325 template<typename Class>
326 const std::type_info& get_type_info() const
327 {
328 return boost::dll::detail::load_type_info<Class>(_lib, _storage);
329 }
330 /**
331 * This function can be used to add a type alias.
332 *
333 * This is to be used, when a class shall be imported, which is not declared on the host side.
334 *
335 * Example:
336 * \code
337 * smart_library lib("test_lib.so");
338 *
339 * lib.add_type_alias<MyAlias>("MyClass"); //when using MyAlias, the library will look for MyClass
340 *
341 * //get the destructor of MyClass
342 * destructor<MyAlias> dtor = lib.get_destructor<MyAlias>();
343 * \endcode
344 *
345 *
346 * \param name Name of the class the alias is for.
347 *
348 * \attention If the alias-type is not large enough for the imported class, it will result in undefined behaviour.
349 * \warning The alias will only be applied for the type signature, it will not replace the token in the scoped name.
350 */
351 template<typename Alias> void add_type_alias(const std::string& name) {
352 this->_storage.add_alias<Alias>(name);
353 }
354
355 //! \copydoc shared_library::unload()
356 void unload() BOOST_NOEXCEPT {
357 _storage.clear();
358 _lib.unload();
359 }
360
361 //! \copydoc shared_library::is_loaded() const
362 bool is_loaded() const BOOST_NOEXCEPT {
363 return _lib.is_loaded();
364 }
365
366 //! \copydoc shared_library::operator!() const
367 bool operator!() const BOOST_NOEXCEPT {
368 return !is_loaded();
369 }
370
371 //! \copydoc shared_library::operator bool() const
372 BOOST_EXPLICIT_OPERATOR_BOOL()
373
374 //! \copydoc shared_library::has(const char* symbol_name) const
375 bool has(const char* symbol_name) const BOOST_NOEXCEPT {
376 return _lib.has(symbol_name);
377 }
378
379 //! \copydoc shared_library::has(const std::string& symbol_name) const
380 bool has(const std::string& symbol_name) const BOOST_NOEXCEPT {
381 return _lib.has(symbol_name);
382 }
383
384 //! \copydoc shared_library::assign(const shared_library& lib)
385 smart_library& assign(const smart_library& lib) {
386 _lib.assign(lib._lib);
387 _storage.assign(lib._storage);
388 return *this;
389 }
390
391 //! \copydoc shared_library::swap(shared_library& rhs)
392 void swap(smart_library& rhs) BOOST_NOEXCEPT {
393 _lib.swap(rhs._lib);
394 _storage.swap(rhs._storage);
395 }
396 };
397
398 /// Very fast equality check that compares the actual DLL/DSO objects. Throws nothing.
399 inline bool operator==(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT {
400 return lhs.shared_lib().native() == rhs.shared_lib().native();
401 }
402
403 /// Very fast inequality check that compares the actual DLL/DSO objects. Throws nothing.
404 inline bool operator!=(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT {
405 return lhs.shared_lib().native() != rhs.shared_lib().native();
406 }
407
408 /// Compare the actual DLL/DSO objects without any guarantee to be stable between runs. Throws nothing.
409 inline bool operator<(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT {
410 return lhs.shared_lib().native() < rhs.shared_lib().native();
411 }
412
413 /// Swaps two shared libraries. Does not invalidate symbols and functions loaded from libraries. Throws nothing.
414 inline void swap(smart_library& lhs, smart_library& rhs) BOOST_NOEXCEPT {
415 lhs.swap(rhs);
416 }
417
418
419 #ifdef BOOST_DLL_DOXYGEN
420 /** Helper functions for overloads.
421 *
422 * Gets either a variable, function or member-function, depending on the signature.
423 *
424 * @code
425 * smart_library sm("lib.so");
426 * get<int>(sm, "space::value"); //import a variable
427 * get<void(int)>(sm, "space::func"); //import a function
428 * get<some_class, void(int)>(sm, "space::class_::mem_fn"); //import a member function
429 * @endcode
430 *
431 * @param sm A reference to the @ref smart_library
432 * @param name The name of the entity to import
433 */
434 template<class T, class T2>
435 void get(const smart_library& sm, const std::string &name);
436 #endif
437
438 template<class T>
439 T& get(const smart_library& sm, const std::string &name, typename boost::enable_if<boost::is_object<T>,T>::type* = nullptr)
440
441 {
442 return sm.get_variable<T>(name);
443 }
444
445 template<class T>
446 auto get(const smart_library& sm, const std::string &name, typename boost::enable_if<boost::is_function<T>>::type* = nullptr)
447 {
448 return sm.get_function<T>(name);
449 }
450
451 template<class Class, class Signature>
452 auto get(const smart_library& sm, const std::string &name) -> typename detail::get_mem_fn_type<Class, Signature>::mem_fn
453 {
454 return sm.get_mem_fn<Class, Signature>(name);
455 }
456
457
458 } /* namespace experimental */
459 } /* namespace dll */
460 } /* namespace boost */
461
462 #endif /* BOOST_DLL_SMART_LIBRARY_HPP_ */