File indexing completed on 2025-09-18 08:37:32
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_DLL_IMPORT_CLASS_HPP_
0009 #define BOOST_DLL_IMPORT_CLASS_HPP_
0010
0011
0012
0013
0014
0015
0016
0017 #include <boost/dll/smart_library.hpp>
0018 #include <boost/dll/import_mangled.hpp>
0019 #include <memory>
0020 #include <utility> // std::move
0021
0022 #if (__cplusplus < 201103L) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201103L)
0023 # error This file requires C++11 at least!
0024 #endif
0025
0026 #ifdef BOOST_HAS_PRAGMA_ONCE
0027 # pragma once
0028 #endif
0029
0030 namespace boost { namespace dll { namespace experimental {
0031
0032 namespace detail
0033 {
0034
0035 template<typename T>
0036 struct deleter
0037 {
0038 destructor<T> dtor;
0039 bool use_deleting;
0040
0041 deleter(const destructor<T> & dtor, bool use_deleting = false) :
0042 dtor(dtor), use_deleting(use_deleting) {}
0043
0044 void operator()(T*t)
0045 {
0046 if (use_deleting)
0047 dtor.call_deleting(t);
0048 else
0049 {
0050 dtor.call_standard(t);
0051
0052 auto p = reinterpret_cast<char*>(t);
0053 delete [] p;
0054 }
0055 }
0056 };
0057
0058 template<class T, class = void>
0059 struct mem_fn_call_proxy;
0060
0061 template<class Class, class U>
0062 struct mem_fn_call_proxy<Class, boost::dll::experimental::detail::mangled_library_mem_fn<Class, U>>
0063 {
0064 typedef boost::dll::experimental::detail::mangled_library_mem_fn<Class, U> mem_fn_t;
0065 Class* t;
0066 mem_fn_t & mem_fn;
0067
0068 mem_fn_call_proxy(mem_fn_call_proxy&&) = default;
0069 mem_fn_call_proxy(const mem_fn_call_proxy & ) = delete;
0070 mem_fn_call_proxy(Class * t, mem_fn_t & mem_fn)
0071 : t(t), mem_fn(mem_fn) {}
0072
0073 template<typename ...Args>
0074 auto operator()(Args&&...args) const -> decltype(mem_fn(t, std::forward<Args>(args)...))
0075 {
0076 return mem_fn(t, std::forward<Args>(args)...);
0077 }
0078
0079 };
0080
0081 template<class T, class Return, class ...Args>
0082 struct mem_fn_call_proxy<T, Return(Args...)>
0083 {
0084 T* t;
0085 const std::string &name;
0086 smart_library &_lib;
0087
0088 mem_fn_call_proxy(mem_fn_call_proxy&&) = default;
0089 mem_fn_call_proxy(const mem_fn_call_proxy&) = delete;
0090 mem_fn_call_proxy(T *t, const std::string &name, smart_library & _lib)
0091 : t(t), name(name), _lib(_lib) {};
0092
0093 Return operator()(Args...args) const
0094 {
0095 auto f = _lib.get_mem_fn<T, Return(Args...)>(name);
0096 return (t->*f)(static_cast<Args>(args)...);
0097 }
0098 };
0099
0100 }
0101
0102 template<typename T>
0103 class imported_class;
0104
0105 template<typename T, typename ... Args> imported_class<T>
0106 import_class(const smart_library& lib, Args...args);
0107 template<typename T, typename ... Args> imported_class<T>
0108 import_class(const smart_library& lib, const std::string & alias_name, Args...args);
0109 template<typename T, typename ... Args> imported_class<T>
0110 import_class(const smart_library& lib, std::size_t size, Args...args);
0111 template<typename T, typename ... Args> imported_class<T>
0112 import_class(const smart_library& lib, std::size_t size,
0113 const std::string & alias_name, Args...args);
0114
0115
0116
0117
0118
0119
0120
0121
0122 template<typename T>
0123 class imported_class
0124 {
0125 smart_library lib_;
0126 std::unique_ptr<T, detail::deleter<T>> data_;
0127 bool is_allocating_;
0128 std::size_t size_;
0129 const std::type_info& ti_;
0130
0131 template<typename ... Args>
0132 inline std::unique_ptr<T, detail::deleter<T>> make_data(const smart_library& lib, Args ... args);
0133 template<typename ... Args>
0134 inline std::unique_ptr<T, detail::deleter<T>> make_data(const smart_library& lib, std::size_t size, Args...args);
0135
0136 template<typename ...Args>
0137 imported_class(detail::sequence<Args...> *, const smart_library& lib, Args...args);
0138
0139 template<typename ...Args>
0140 imported_class(detail::sequence<Args...> *, const smart_library& lib, std::size_t size, Args...args);
0141
0142 template<typename ...Args>
0143 imported_class(detail::sequence<Args...> *, smart_library&& lib, Args...args);
0144
0145 template<typename ...Args>
0146 imported_class(detail::sequence<Args...> *, smart_library&& lib, std::size_t size, Args...args);
0147 public:
0148
0149 template<typename ...Args>
0150 static imported_class<T> make(smart_library&& lib, Args...args)
0151 {
0152 typedef detail::sequence<Args...> *seq;
0153 return imported_class(seq(), std::move(lib), static_cast<Args>(args)...);
0154 }
0155
0156 template<typename ...Args>
0157 static imported_class<T> make(smart_library&& lib, std::size_t size, Args...args)
0158 {
0159 typedef detail::sequence<Args...> *seq;
0160 return imported_class(seq(), std::move(lib), size, static_cast<Args>(args)...);
0161 }
0162 template<typename ...Args>
0163 static imported_class<T> make(const smart_library& lib, Args...args)
0164 {
0165 typedef detail::sequence<Args...> *seq;
0166 return imported_class(seq(), lib, static_cast<Args>(args)...);
0167 }
0168
0169 template<typename ...Args>
0170 static imported_class<T> make(const smart_library& lib, std::size_t size, Args...args)
0171 {
0172 typedef detail::sequence<Args...> *seq;
0173 return imported_class(seq(), lib, size, static_cast<Args>(args)...);
0174 }
0175
0176 typedef imported_class<T> base_t;
0177
0178 T* get() {return data_.get();}
0179 imported_class() = delete;
0180
0181 imported_class(imported_class&) = delete;
0182 imported_class(imported_class&&) = default;
0183 imported_class& operator=(imported_class&) = delete;
0184 imported_class& operator=(imported_class&&) = default;
0185
0186
0187 bool is_move_constructible() {return !lib_.symbol_storage().template get_constructor<T(T&&)> ().empty();}
0188
0189 bool is_move_assignable() {return !lib_.symbol_storage().template get_mem_fn<T, T&(T&&)> ("operator=").empty();}
0190
0191 bool is_copy_constructible() {return !lib_.symbol_storage().template get_constructor<T(const T&)>().empty();}
0192
0193 bool is_copy_assignable() {return !lib_.symbol_storage().template get_mem_fn<T, T&(const T&)>("operator=").empty();}
0194
0195 imported_class<T> copy() const;
0196 imported_class<T> move();
0197
0198
0199 void copy_assign(const imported_class<T> & lhs) const;
0200
0201 void move_assign( imported_class<T> & lhs);
0202
0203
0204 explicit operator bool() const {return data_;}
0205
0206
0207 const std::type_info& get_type_info() {return ti_;};
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 template<class Signature>
0219 const detail::mem_fn_call_proxy<T, Signature> call(const std::string& name)
0220 {
0221 return detail::mem_fn_call_proxy<T, Signature>(data_.get(), name, lib_);
0222 }
0223
0224
0225
0226
0227
0228
0229
0230
0231 template<class Tin, class Signature, class = boost::enable_if<detail::unqalified_is_same<T, Tin>>>
0232 const detail::mem_fn_call_proxy<Tin, Signature> call(const std::string& name)
0233 {
0234 return detail::mem_fn_call_proxy<Tin, Signature>(data_.get(), name, lib_);
0235 }
0236
0237 template<class Tin, class T2>
0238 const detail::mem_fn_call_proxy<Tin, boost::dll::experimental::detail::mangled_library_mem_fn<Tin, T2>>
0239 operator->*(detail::mangled_library_mem_fn<Tin, T2>& mn)
0240 {
0241 return detail::mem_fn_call_proxy<Tin, boost::dll::experimental::detail::mangled_library_mem_fn<Tin, T2>>(data_.get(), mn);
0242 }
0243
0244
0245 template <class ...Args>
0246 typename boost::dll::experimental::detail::mangled_import_type<boost::dll::experimental::detail::sequence<T, Args...>>::type
0247 import(const std::string & name)
0248 {
0249 return boost::dll::experimental::import_mangled<T, Args...>(lib_, name);
0250 }
0251 };
0252
0253
0254
0255
0256 template<typename T>
0257 template<typename ... Args>
0258 inline std::unique_ptr<T, detail::deleter<T>> imported_class<T>::make_data(const smart_library& lib, Args ... args)
0259 {
0260 constructor<T(Args...)> ctor = lib.get_constructor<T(Args...)>();
0261 destructor<T> dtor = lib.get_destructor <T>();
0262
0263 if (!ctor.has_allocating() || !dtor.has_deleting())
0264 {
0265 std::error_code ec = std::make_error_code(
0266 std::errc::bad_file_descriptor
0267 );
0268
0269
0270 boost::throw_exception(
0271 boost::dll::fs::system_error(
0272 ec, "boost::dll::detail::make_data() failed: no allocating ctor or dtor was found"
0273 )
0274 );
0275 }
0276
0277 return std::unique_ptr<T, detail::deleter<T>> (
0278 ctor.call_allocating(static_cast<Args>(args)...),
0279 detail::deleter<T>(dtor, false ));
0280 }
0281
0282
0283 template<typename T>
0284 template<typename ... Args>
0285 inline std::unique_ptr<T, detail::deleter<T>> imported_class<T>::make_data(const smart_library& lib, std::size_t size, Args...args)
0286 {
0287 constructor<T(Args...)> ctor = lib.get_constructor<T(Args...)>();
0288 destructor<T> dtor = lib.get_destructor <T>();
0289
0290 if (!ctor.has_standard() || !dtor.has_standard())
0291 {
0292 std::error_code ec = std::make_error_code(
0293 std::errc::bad_file_descriptor
0294 );
0295
0296
0297 boost::throw_exception(
0298 boost::dll::fs::system_error(
0299 ec, "boost::dll::detail::make_data() failed: no regular ctor or dtor was found"
0300 )
0301 );
0302 }
0303
0304 T *data = reinterpret_cast<T*>(new char[size]);
0305
0306 ctor.call_standard(data, static_cast<Args>(args)...);
0307
0308 return std::unique_ptr<T, detail::deleter<T>> (
0309 reinterpret_cast<T*>(data),
0310 detail::deleter<T>(dtor, false ));
0311
0312 }
0313
0314
0315 template<typename T>
0316 template<typename ...Args>
0317 imported_class<T>::imported_class(detail::sequence<Args...> *, const smart_library & lib, Args...args)
0318 : lib_(lib),
0319 data_(make_data<Args...>(lib_, static_cast<Args>(args)...)),
0320 is_allocating_(false),
0321 size_(0),
0322 ti_(lib.get_type_info<T>())
0323 {
0324
0325 }
0326
0327 template<typename T>
0328 template<typename ...Args>
0329 imported_class<T>::imported_class(detail::sequence<Args...> *, const smart_library & lib, std::size_t size, Args...args)
0330 : lib_(lib),
0331 data_(make_data<Args...>(lib_, size, static_cast<Args>(args)...)),
0332 is_allocating_(true),
0333 size_(size),
0334 ti_(lib.get_type_info<T>())
0335 {
0336
0337 }
0338
0339 template<typename T>
0340 template<typename ...Args>
0341 imported_class<T>::imported_class(detail::sequence<Args...> *, smart_library && lib, Args...args)
0342 : lib_(std::move(lib)),
0343 data_(make_data<Args...>(lib_, static_cast<Args>(args)...)),
0344 is_allocating_(false),
0345 size_(0),
0346 ti_(lib.get_type_info<T>())
0347 {
0348
0349 }
0350
0351 template<typename T>
0352 template<typename ...Args>
0353 imported_class<T>::imported_class(detail::sequence<Args...> *, smart_library && lib, std::size_t size, Args...args)
0354 : lib_(std::move(lib)),
0355 data_(make_data<Args...>(lib_, size, static_cast<Args>(args)...)),
0356 is_allocating_(true),
0357 size_(size),
0358 ti_(lib.get_type_info<T>())
0359 {
0360
0361 }
0362
0363 template<typename T>
0364 inline imported_class<T> boost::dll::experimental::imported_class<T>::copy() const
0365 {
0366 if (this->is_allocating_)
0367 return imported_class<T>::template make<const T&>(lib_, *data_);
0368 else
0369 return imported_class<T>::template make<const T&>(lib_, size_, *data_);
0370 }
0371
0372 template<typename T>
0373 inline imported_class<T> boost::dll::experimental::imported_class<T>::move()
0374 {
0375 if (this->is_allocating_)
0376 return imported_class<T>::template make<T&&>(lib_, *data_);
0377 else
0378 return imported_class<T>::template make<T&&>(lib_, size_, *data_);
0379 }
0380
0381 template<typename T>
0382 inline void boost::dll::experimental::imported_class<T>::copy_assign(const imported_class<T>& lhs) const
0383 {
0384 this->call<T&(const T&)>("operator=")(*lhs.data_);
0385 }
0386
0387 template<typename T>
0388 inline void boost::dll::experimental::imported_class<T>::move_assign(imported_class<T>& lhs)
0389 {
0390 this->call<T&(T&&)>("operator=")(static_cast<T&&>(*lhs.data_));
0391 }
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424 template<typename T, typename ... Args> imported_class<T>
0425 import_class(smart_library lib, std::size_t size, Args...args)
0426 {
0427 return imported_class<T>::template make<Args...>(std::move(lib), size, static_cast<Args>(args)...);
0428 }
0429
0430
0431 template<typename T, typename ... Args> imported_class<T>
0432 import_class(smart_library lib, Args...args)
0433 {
0434 return imported_class<T>::template make<Args...>(std::move(lib), static_cast<Args>(args)...);
0435 }
0436
0437
0438 template<typename T, typename ... Args> imported_class<T>
0439 import_class(smart_library lib, const std::string & alias_name, Args...args)
0440 {
0441 lib.add_type_alias<T>(alias_name);
0442 return imported_class<T>::template make<Args...>(std::move(lib), static_cast<Args>(args)...);
0443 }
0444
0445
0446 template<typename T, typename ... Args> imported_class<T>
0447 import_class(smart_library lib, std::size_t size, const std::string & alias_name, Args...args)
0448 {
0449 lib.add_type_alias<T>(alias_name);
0450 return imported_class<T>::template make<Args...>(std::move(lib), size, static_cast<Args>(args)...);
0451 }
0452
0453
0454 template<typename T, typename ... Args> imported_class<T>
0455 import_class(smart_library lib, const std::string & alias_name, std::size_t size, Args...args)
0456 {
0457 lib.add_type_alias<T>(alias_name);
0458 return imported_class<T>::template make<Args...>(std::move(lib), size, static_cast<Args>(args)...);
0459 }
0460
0461
0462
0463
0464
0465
0466 template<typename T, typename ... Args> imported_class<T>
0467 import_class(smart_library & lib, Args...args)
0468 {
0469 return imported_class<T>::template make<Args...>(lib, static_cast<Args>(args)...);
0470 }
0471
0472
0473
0474
0475 template<typename T, typename ... Args> imported_class<T>
0476 import_class(smart_library & lib, const std::string & alias_name, Args...args)
0477 {
0478 lib.add_type_alias<T>(alias_name);
0479 return imported_class<T>::template make<Args...>(lib, static_cast<Args>(args)...);
0480 }
0481
0482
0483
0484
0485 template<typename T, typename ... Args> imported_class<T>
0486 import_class(smart_library & lib, std::size_t size, Args...args)
0487 {
0488 return imported_class<T>::template make<Args...>(lib, size, static_cast<Args>(args)...);
0489 }
0490
0491
0492
0493
0494 template<typename T, typename ... Args> imported_class<T>
0495 import_class(smart_library & lib, std::size_t size, const std::string & alias_name, Args...args)
0496 {
0497 lib.add_type_alias<T>(alias_name);
0498 return imported_class<T>::template make<Args...>(lib, size, static_cast<Args>(args)...);
0499 }
0500
0501
0502
0503
0504 template<typename T, typename ... Args> imported_class<T>
0505 import_class(smart_library & lib, const std::string & alias_name, std::size_t size, Args...args)
0506 {
0507 lib.add_type_alias<T>(alias_name);
0508 return imported_class<T>::template make<Args...>(lib, size, static_cast<Args>(args)...);
0509 }
0510
0511 }
0512 }
0513 }
0514
0515
0516
0517 #endif