]>
Commit | Line | Data |
---|---|---|
1 | // Copyright 2014 Renato Tegon Forti, Antony Polukhin. | |
2 | // Copyright 2015-2016 Antony Polukhin. | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. | |
5 | // (See accompanying file LICENSE_1_0.txt | |
6 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #ifndef BOOST_DLL_IMPORT_HPP | |
9 | #define BOOST_DLL_IMPORT_HPP | |
10 | ||
11 | #include <boost/config.hpp> | |
12 | #include <boost/utility/enable_if.hpp> | |
13 | #include <boost/type_traits/is_object.hpp> | |
14 | #include <boost/make_shared.hpp> | |
15 | #include <boost/dll/shared_library.hpp> | |
16 | #include <boost/utility/addressof.hpp> | |
17 | #include <boost/move/move.hpp> | |
18 | ||
19 | #if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
20 | # include <boost/function.hpp> | |
21 | #endif | |
22 | ||
23 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
24 | # pragma once | |
25 | #endif | |
26 | ||
27 | /// \file boost/dll/import.hpp | |
28 | /// \brief Contains all the boost::dll::import* reference counting | |
29 | /// functions that hold a shared pointer to the instance of | |
30 | /// boost::dll::shared_library. | |
31 | ||
32 | namespace boost { namespace dll { | |
33 | ||
34 | ||
35 | namespace detail { | |
36 | ||
37 | template <class T> | |
38 | class library_function { | |
39 | // Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster. | |
40 | boost::shared_ptr<T> f_; | |
41 | ||
42 | public: | |
43 | inline library_function(const boost::shared_ptr<shared_library>& lib, T* func_ptr) BOOST_NOEXCEPT | |
44 | : f_(lib, func_ptr) | |
45 | {} | |
46 | ||
47 | #if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
48 | operator T*() const BOOST_NOEXCEPT { | |
49 | return f_.get(); | |
50 | } | |
51 | #else | |
52 | ||
53 | // Compilation error at this point means that imported function | |
54 | // was called with unmatching parameters. | |
55 | // | |
56 | // Example: | |
57 | // auto f = dll::import<void(int)>("function", "lib.so"); | |
58 | // f("Hello"); // error: invalid conversion from 'const char*' to 'int' | |
59 | // f(1, 2); // error: too many arguments to function | |
60 | // f(); // error: too few arguments to function | |
61 | template <class... Args> | |
62 | inline auto operator()(Args&&... args) const | |
63 | -> decltype( (*f_)(static_cast<Args&&>(args)...) ) | |
64 | { | |
65 | return (*f_)(static_cast<Args&&>(args)...); | |
66 | } | |
67 | #endif | |
68 | }; | |
69 | ||
70 | template <class T, class = void> | |
71 | struct import_type; | |
72 | ||
73 | template <class T> | |
74 | struct import_type<T, typename boost::disable_if<boost::is_object<T> >::type> { | |
75 | typedef boost::dll::detail::library_function<T> base_type; | |
76 | ||
77 | #if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
78 | typedef boost::function<T> type; | |
79 | #else | |
80 | typedef boost::dll::detail::library_function<T> type; | |
81 | #endif | |
82 | }; | |
83 | ||
84 | template <class T> | |
85 | struct import_type<T, typename boost::enable_if<boost::is_object<T> >::type> { | |
86 | typedef boost::shared_ptr<T> base_type; | |
87 | typedef boost::shared_ptr<T> type; | |
88 | }; | |
89 | } // namespace detail | |
90 | ||
91 | ||
92 | #ifndef BOOST_DLL_DOXYGEN | |
93 | # define BOOST_DLL_IMPORT_RESULT_TYPE inline typename boost::dll::detail::import_type<T>::type | |
94 | #endif | |
95 | ||
96 | ||
97 | /*! | |
98 | * Returns callable object or boost::shared_ptr<T> that holds the symbol imported | |
99 | * from the loaded library. Returned value refcounts usage | |
100 | * of the loaded shared library, so that it won't get unload until all copies of return value | |
101 | * are not destroyed. | |
102 | * | |
103 | * This call will succeed if call to \forcedlink{shared_library}`::has(const char* )` | |
104 | * function with the same symbol name returned `true`. | |
105 | * | |
106 | * For importing symbols by \b alias names use \forcedlink{import_alias} method. | |
107 | * | |
108 | * \b Examples: | |
109 | * | |
110 | * \code | |
111 | * boost::function<int(int)> f = import<int(int)>("test_lib.so", "integer_func_name"); | |
112 | * | |
113 | * auto f_cpp11 = import<int(int)>("test_lib.so", "integer_func_name"); | |
114 | * \endcode | |
115 | * | |
116 | * \code | |
117 | * boost::shared_ptr<int> i = import<int>("test_lib.so", "integer_name"); | |
118 | * \endcode | |
119 | * | |
120 | * \b Template \b parameter \b T: Type of the symbol that we are going to import. Must be explicitly specified. | |
121 | * | |
122 | * \param lib Path to shared library or shared library to load function from. | |
123 | * \param name Null-terminated C or C++ mangled name of the function to import. Can handle std::string, char*, const char*. | |
124 | * \param mode An mode that will be used on library load. | |
125 | * | |
126 | * \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type. | |
127 | * | |
128 | * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded. | |
129 | * Overload that accepts path also throws std::bad_alloc in case of insufficient memory. | |
130 | */ | |
131 | template <class T> | |
132 | BOOST_DLL_IMPORT_RESULT_TYPE import(const boost::filesystem::path& lib, const char* name, | |
133 | load_mode::type mode = load_mode::default_mode) | |
134 | { | |
135 | typedef typename boost::dll::detail::import_type<T>::base_type type; | |
136 | ||
137 | boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib, mode); | |
138 | return type(p, boost::addressof(p->get<T>(name))); | |
139 | } | |
140 | ||
141 | //! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
142 | template <class T> | |
143 | BOOST_DLL_IMPORT_RESULT_TYPE import(const boost::filesystem::path& lib, const std::string& name, | |
144 | load_mode::type mode = load_mode::default_mode) | |
145 | { | |
146 | return import<T>(lib, name.c_str(), mode); | |
147 | } | |
148 | ||
149 | //! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
150 | template <class T> | |
151 | BOOST_DLL_IMPORT_RESULT_TYPE import(const shared_library& lib, const char* name) { | |
152 | typedef typename boost::dll::detail::import_type<T>::base_type type; | |
153 | ||
154 | boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib); | |
155 | return type(p, boost::addressof(p->get<T>(name))); | |
156 | } | |
157 | ||
158 | //! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
159 | template <class T> | |
160 | BOOST_DLL_IMPORT_RESULT_TYPE import(const shared_library& lib, const std::string& name) { | |
161 | return import<T>(lib, name.c_str()); | |
162 | } | |
163 | ||
164 | //! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
165 | template <class T> | |
166 | BOOST_DLL_IMPORT_RESULT_TYPE import(BOOST_RV_REF(shared_library) lib, const char* name) { | |
167 | typedef typename boost::dll::detail::import_type<T>::base_type type; | |
168 | ||
169 | boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>( | |
170 | boost::move(lib) | |
171 | ); | |
172 | return type(p, boost::addressof(p->get<T>(name))); | |
173 | } | |
174 | ||
175 | //! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
176 | template <class T> | |
177 | BOOST_DLL_IMPORT_RESULT_TYPE import(BOOST_RV_REF(shared_library) lib, const std::string& name) { | |
178 | return import<T>(boost::move(lib), name.c_str()); | |
179 | } | |
180 | ||
181 | ||
182 | ||
183 | ||
184 | /*! | |
185 | * Returns callable object or boost::shared_ptr<T> that holds the symbol imported | |
186 | * from the loaded library. Returned value refcounts usage | |
187 | * of the loaded shared library, so that it won't get unload until all copies of return value | |
188 | * are not destroyed. | |
189 | * | |
190 | * This call will succeed if call to \forcedlink{shared_library}`::has(const char* )` | |
191 | * function with the same symbol name returned `true`. | |
192 | * | |
193 | * For importing symbols by \b non \b alias names use \forcedlink{import} method. | |
194 | * | |
195 | * \b Examples: | |
196 | * | |
197 | * \code | |
198 | * boost::function<int(int)> f = import_alias<int(int)>("test_lib.so", "integer_func_alias_name"); | |
199 | * | |
200 | * auto f_cpp11 = import_alias<int(int)>("test_lib.so", "integer_func_alias_name"); | |
201 | * \endcode | |
202 | * | |
203 | * \code | |
204 | * boost::shared_ptr<int> i = import_alias<int>("test_lib.so", "integer_alias_name"); | |
205 | * \endcode | |
206 | * | |
207 | * \code | |
208 | * \endcode | |
209 | * | |
210 | * \b Template \b parameter \b T: Type of the symbol alias that we are going to import. Must be explicitly specified. | |
211 | * | |
212 | * \param lib Path to shared library or shared library to load function from. | |
213 | * \param name Null-terminated C or C++ mangled name of the function or variable to import. Can handle std::string, char*, const char*. | |
214 | * \param mode An mode that will be used on library load. | |
215 | * | |
216 | * \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type. | |
217 | * | |
218 | * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded. | |
219 | * Overload that accepts path also throws std::bad_alloc in case of insufficient memory. | |
220 | */ | |
221 | template <class T> | |
222 | BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::filesystem::path& lib, const char* name, | |
223 | load_mode::type mode = load_mode::default_mode) | |
224 | { | |
225 | typedef typename boost::dll::detail::import_type<T>::base_type type; | |
226 | ||
227 | boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib, mode); | |
228 | return type(p, p->get<T*>(name)); | |
229 | } | |
230 | ||
231 | //! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
232 | template <class T> | |
233 | BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::filesystem::path& lib, const std::string& name, | |
234 | load_mode::type mode = load_mode::default_mode) | |
235 | { | |
236 | return import_alias<T>(lib, name.c_str(), mode); | |
237 | } | |
238 | ||
239 | //! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
240 | template <class T> | |
241 | BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const shared_library& lib, const char* name) { | |
242 | typedef typename boost::dll::detail::import_type<T>::base_type type; | |
243 | ||
244 | boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib); | |
245 | return type(p, p->get<T*>(name)); | |
246 | } | |
247 | ||
248 | //! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
249 | template <class T> | |
250 | BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const shared_library& lib, const std::string& name) { | |
251 | return import_alias<T>(lib, name.c_str()); | |
252 | } | |
253 | ||
254 | //! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
255 | template <class T> | |
256 | BOOST_DLL_IMPORT_RESULT_TYPE import_alias(BOOST_RV_REF(shared_library) lib, const char* name) { | |
257 | typedef typename boost::dll::detail::import_type<T>::base_type type; | |
258 | ||
259 | boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>( | |
260 | boost::move(lib) | |
261 | ); | |
262 | return type(p, p->get<T*>(name)); | |
263 | } | |
264 | ||
265 | //! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode) | |
266 | template <class T> | |
267 | BOOST_DLL_IMPORT_RESULT_TYPE import_alias(BOOST_RV_REF(shared_library) lib, const std::string& name) { | |
268 | return import_alias<T>(boost::move(lib), name.c_str()); | |
269 | } | |
270 | ||
271 | #undef BOOST_DLL_IMPORT_RESULT_TYPE | |
272 | ||
273 | ||
274 | }} // boost::dll | |
275 | ||
276 | #endif // BOOST_DLL_IMPORT_HPP | |
277 |