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