diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 9ff1c73..a96bf33 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -58,6 +58,7 @@ doxygen autodoc_shared_library_core ../include/boost/dll/alias.hpp ../include/boost/dll/smart_library.hpp + ../include/boost/dll/import_class.hpp ] : $(doxygen_params) diff --git a/doc/mangled.qbk b/doc/mangled.qbk index 2fc1546..8ee08be 100644 --- a/doc/mangled.qbk +++ b/doc/mangled.qbk @@ -10,7 +10,26 @@ [section Mangled Import] -This section describes the experimental feature of allowing the import of mangled symbols from an dll. While this feature is unique to this library and looks quite promising, it is not throroughly tested and thus not considered stable. +This section describes the experimental feature of allowing the import of mangled symbols from an dll. While this feature is unique to this library and looks quite promising, it is not throroughly tested and thus not considered stable. + +As a short example we can import the following functions quite easily: + +``` +//library.dll +namespace foo { +int bar(int); +double bar(double); +} +``` + +And the import looks like this: + +``` +auto f1 = import_mangled("library.dll", "foo::bar"); +auto f2 = import_mangled("library.dll", "foo::bar"); +cout << f1(42) << endl; +cout << f2(3.2) << endl; +``` [section Support & Requirements] diff --git a/example/mangled/smart_lib.cpp b/example/mangled/smart_lib.cpp index 3ff8778..e6bdf05 100644 --- a/example/mangled/smart_lib.cpp +++ b/example/mangled/smart_lib.cpp @@ -23,7 +23,7 @@ int main(int argc, char* argv[]) { //[smart_lib_size auto size_f = lib.get_function("space::my_plugin::size"); //get the size function - auto size = (*size_f)(); // get the size of the class + auto size = size_f(); // get the size of the class std::unique_ptr buffer(new char[size]); //allocate a buffer for the import alias & inst = *reinterpret_cast(buffer.get()); //cast it to our alias type. //] diff --git a/include/boost/dll/detail/demangling/itanium.hpp b/include/boost/dll/detail/demangling/itanium.hpp index a05e738..2701a03 100644 --- a/include/boost/dll/detail/demangling/itanium.hpp +++ b/include/boost/dll/detail/demangling/itanium.hpp @@ -27,12 +27,12 @@ class mangled_storage_impl : public mangled_storage_base struct dummy {}; template - std::vector get_func_params(dummy) + std::vector get_func_params(dummy) const { return {get_name()...}; } template - std::string get_return_type(dummy) + std::string get_return_type(dummy) const { return get_name(); } @@ -62,25 +62,25 @@ public: }; template - std::string get_variable(const std::string &name); + std::string get_variable(const std::string &name) const; template - std::string get_function(const std::string &name); + std::string get_function(const std::string &name) const; template - std::string get_mem_fn(const std::string &name); + std::string get_mem_fn(const std::string &name) const; template - ctor_sym get_constructor(); + ctor_sym get_constructor() const; template - dtor_sym get_destructor(); + dtor_sym get_destructor() const; template - std::string get_type_info(); + std::string get_type_info() const; template - std::vector get_related(); + std::vector get_related() const; }; @@ -146,7 +146,7 @@ namespace parser -template std::string mangled_storage_impl::get_variable(const std::string &name) +template std::string mangled_storage_impl::get_variable(const std::string &name) const { auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == name;}); @@ -157,7 +157,7 @@ template std::string mangled_storage_impl::get_variable(const std::s return ""; } -template std::string mangled_storage_impl::get_function(const std::string &name) +template std::string mangled_storage_impl::get_function(const std::string &name) const { using func_type = Func*; @@ -172,7 +172,7 @@ template std::string mangled_storage_impl::get_function(const std } template -std::string mangled_storage_impl::get_mem_fn(const std::string &name) +std::string mangled_storage_impl::get_mem_fn(const std::string &name) const { using namespace parser; @@ -195,7 +195,7 @@ std::string mangled_storage_impl::get_mem_fn(const std::string &name) template -auto mangled_storage_impl::get_constructor() -> ctor_sym +auto mangled_storage_impl::get_constructor() const -> ctor_sym { using namespace parser; @@ -242,7 +242,7 @@ auto mangled_storage_impl::get_constructor() -> ctor_sym } template -auto mangled_storage_impl::get_destructor() -> dtor_sym +auto mangled_storage_impl::get_destructor() const -> dtor_sym { std::string dtor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name @@ -286,7 +286,7 @@ auto mangled_storage_impl::get_destructor() -> dtor_sym } template -std::string mangled_storage_impl::get_type_info() +std::string mangled_storage_impl::get_type_info() const { std::string id = "typeinfo for " + get_name(); @@ -306,7 +306,7 @@ std::string mangled_storage_impl::get_type_info() } template -std::vector mangled_storage_impl::get_related() +std::vector mangled_storage_impl::get_related() const { std::vector ret; auto name = get_name(); diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 76e2757..b5d526b 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -27,12 +27,12 @@ class mangled_storage_impl : public mangled_storage_base struct dummy {}; template - std::vector get_func_params(dummy) + std::vector get_func_params(dummy) const { return {get_name()...}; } template - std::string get_return_type(dummy) + std::string get_return_type(dummy) const { return get_name(); } @@ -46,19 +46,19 @@ public: using mangled_storage_base::mangled_storage_base; template - std::string get_variable(const std::string &name); + std::string get_variable(const std::string &name) const; template - std::string get_function(const std::string &name); + std::string get_function(const std::string &name) const; template - std::string get_mem_fn(const std::string &name); + std::string get_mem_fn(const std::string &name) const; template - ctor_sym get_constructor(); + ctor_sym get_constructor() const; template - dtor_sym get_destructor(); + dtor_sym get_destructor() const; template //overload, does not need to virtual. std::string get_name() const @@ -69,10 +69,10 @@ public: } template - std::string get_vtable(); + std::string get_vtable() const; template - std::vector get_related(); + std::vector get_related() const; }; @@ -192,7 +192,7 @@ namespace parser } -template std::string mangled_storage_impl::get_variable(const std::string &name) +template std::string mangled_storage_impl::get_variable(const std::string &name) const { using namespace std; using namespace boost; @@ -226,7 +226,7 @@ template std::string mangled_storage_impl::get_variable(const std::s return ""; } -template std::string mangled_storage_impl::get_function(const std::string &name) +template std::string mangled_storage_impl::get_function(const std::string &name) const { namespace x3 = spirit::x3; using namespace parser; @@ -264,7 +264,7 @@ template std::string mangled_storage_impl::get_function(const std } template -std::string mangled_storage_impl::get_mem_fn(const std::string &name) +std::string mangled_storage_impl::get_mem_fn(const std::string &name) const { namespace x3 = spirit::x3; using namespace parser; @@ -302,7 +302,7 @@ std::string mangled_storage_impl::get_mem_fn(const std::string &name) template -auto mangled_storage_impl::get_constructor() -> ctor_sym +auto mangled_storage_impl::get_constructor() const -> ctor_sym { namespace x3 = spirit::x3; using namespace parser; @@ -352,7 +352,7 @@ auto mangled_storage_impl::get_constructor() -> ctor_sym } template -auto mangled_storage_impl::get_destructor() -> dtor_sym +auto mangled_storage_impl::get_destructor() const -> dtor_sym { namespace x3 = spirit::x3; using namespace parser; @@ -398,7 +398,7 @@ auto mangled_storage_impl::get_destructor() -> dtor_sym } template -std::string mangled_storage_impl::get_vtable() +std::string mangled_storage_impl::get_vtable() const { std::string id = "const " + get_name() + "::`vftable'"; @@ -417,7 +417,7 @@ std::string mangled_storage_impl::get_vtable() } template -std::vector mangled_storage_impl::get_related() +std::vector mangled_storage_impl::get_related() const { std::vector ret; auto name = get_name(); diff --git a/include/boost/dll/import_class.hpp b/include/boost/dll/import_class.hpp index fa72840..c3fa3b6 100644 --- a/include/boost/dll/import_class.hpp +++ b/include/boost/dll/import_class.hpp @@ -11,7 +11,6 @@ #include #include - #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif @@ -92,87 +91,137 @@ template class imported_class; template imported_class -import_class(const boost::shared_ptr& lib, Args...args); +import_class(const smart_library& lib, Args...args); template imported_class -import_class(const boost::shared_ptr& lib, const std::string & alias_name, Args...args); +import_class(const smart_library& lib, const std::string & alias_name, Args...args); template imported_class -import_class(const boost::shared_ptr& lib, std::size_t size, Args...args); +import_class(const smart_library& lib, std::size_t size, Args...args); template imported_class -import_class(const boost::shared_ptr& lib, std::size_t size, +import_class(const smart_library& lib, std::size_t size, const std::string & alias_name, Args...args); + +/*! This class represents an imported class. + * + * \note It must be constructed via \ref boost::dll::import_class(const smart_library& lib, std::size_t, Args...) + * + * \tparam The type or type-alias of the imported class. + */ template class imported_class { - boost::shared_ptr _lib; + smart_library _lib; std::unique_ptr> _data; bool _is_allocating; std::size_t _size; const std::type_info& _ti; template - inline std::unique_ptr> make_data(const boost::shared_ptr& lib, Args ... args); + inline std::unique_ptr> make_data(const smart_library& lib, Args ... args); template - inline std::unique_ptr> make_data(const boost::shared_ptr& lib, std::size_t size, Args...args); + inline std::unique_ptr> make_data(const smart_library& lib, std::size_t size, Args...args); template - imported_class(detail::sequence *, const boost::shared_ptr& lib, Args...args); + imported_class(detail::sequence *, const smart_library& lib, Args...args); template - imported_class(detail::sequence *, const boost::shared_ptr& lib, std::size_t size, Args...args); + imported_class(detail::sequence *, const smart_library& lib, std::size_t size, Args...args); + + template + imported_class(detail::sequence *, smart_library&& lib, Args...args); + + template + imported_class(detail::sequence *, smart_library&& lib, std::size_t size, Args...args); public: //alias to construct with explicit parameter list template - static imported_class make(const boost::shared_ptr& lib, Args...args) + static imported_class make(smart_library&& lib, Args...args) + { + typedef detail::sequence *seq; + return imported_class(seq(), boost::move(lib), static_cast(args)...); + } + + template + static imported_class make(smart_library&& lib, std::size_t size, Args...args) + { + typedef detail::sequence *seq; + return imported_class(seq(), boost::move(lib), size, static_cast(args)...); + } + template + static imported_class make(const smart_library& lib, Args...args) { typedef detail::sequence *seq; return imported_class(seq(), lib, static_cast(args)...); } template - static imported_class make(const boost::shared_ptr& lib, std::size_t size, Args...args) + static imported_class make(const smart_library& lib, std::size_t size, Args...args) { typedef detail::sequence *seq; return imported_class(seq(), lib, size, static_cast(args)...); } typedef imported_class base_t; + ///Returns a pointer to the underlying class T* get() {return _data.get();} imported_class() = delete; imported_class(imported_class&) = delete; - imported_class(imported_class&&) = default; + imported_class(imported_class&&) = default; /// ().empty();} + ///Check if the imported class is move-assignable + bool is_move_assignable() {return !_lib.symbol_storage().template get_mem_fn ("operator=").empty();} + ///Check if the imported class is copy-constructible + bool is_copy_constructible() {return !_lib.symbol_storage().template get_constructor().empty();} + ///Check if the imported class is copy-assignable + bool is_copy_assignable() {return !_lib.symbol_storage().template get_mem_fn("operator=").empty();} - bool is_move_constructible() {return !_lib->symbol_storage().template get_constructor ().empty();} - bool is_move_assignable() {return !_lib->symbol_storage().template get_mem_fn ("operator=").empty();} - bool is_copy_constructible() {return !_lib->symbol_storage().template get_constructor().empty();} - bool is_copy_assignable() {return !_lib->symbol_storage().template get_mem_fn("operator=").empty();} - - imported_class copy(); - imported_class move(); + imported_class copy() const; /// move(); /// & lhs) const; + ///Invoke the move assignment. \attention Undefined behaviour if the imported object is not move assignable. void move_assign( imported_class & lhs); + ///Check if the class is loaded. explicit operator bool() const {return _data;} + ///Get a const reference to the std::type_info. const std::type_info& get_type_info() {return _ti;}; + /*! Call a member function. This returns a proxy to the function. + * The proxy mechanic mechanic is necessary, so the signaute can be passed. + * + * \b Example + * + * \code + * im_class.call("function_name")("MyString"); + * \endcode + */ template const detail::mem_fn_call_proxy call(const std::string& name) { - return detail::mem_fn_call_proxy(_data.get(), name, *_lib); + return detail::mem_fn_call_proxy(_data.get(), name, _lib); } - //overload for const/volatile functions. + /*! Call a qualified member function, i.e. const and or volatile. + * + * \b Example + * + * \code + * im_class.call("function_name")("MyString"); + * \endcode + */ template>> const detail::mem_fn_call_proxy call(const std::string& name) { - return detail::mem_fn_call_proxy(_data.get(), name, *_lib); + return detail::mem_fn_call_proxy(_data.get(), name, _lib); } - + ///Overload of ->* for an imported method. template const detail::mem_fn_call_proxy> operator->*(detail::mangled_library_mem_fn& mn) @@ -180,7 +229,7 @@ public: return detail::mem_fn_call_proxy>(_data.get(), mn); } - + ///Import a method of the class. template typename boost::dll::experimental::detail::mangled_import_type>::type import(const std::string & name) @@ -194,10 +243,11 @@ public: //helper function, uses the allocating template template -inline std::unique_ptr> imported_class::make_data(const boost::shared_ptr& lib, Args ... args) +inline std::unique_ptr> imported_class::make_data(const smart_library& lib, Args ... args) { - constructor ctor = lib->get_constructor(); - destructor dtor = lib->get_destructor (); + constructor ctor = lib.get_constructor(); + destructor dtor = lib.get_destructor (); + if (!ctor.has_allocating() || !dtor.has_deleting()) { boost::system::error_code ec; @@ -223,10 +273,10 @@ inline std::unique_ptr> imported_class::make_data(const //helper function, using the standard template template -inline std::unique_ptr> imported_class::make_data(const boost::shared_ptr& lib, std::size_t size, Args...args) +inline std::unique_ptr> imported_class::make_data(const smart_library& lib, std::size_t size, Args...args) { - constructor ctor = lib->get_constructor(); - destructor dtor = lib->get_destructor (); + constructor ctor = lib.get_constructor(); + destructor dtor = lib.get_destructor (); if (!ctor.has_standard() || !dtor.has_standard()) { @@ -258,30 +308,54 @@ inline std::unique_ptr> imported_class::make_data(const template template -imported_class::imported_class(detail::sequence *, const boost::shared_ptr & lib, Args...args) +imported_class::imported_class(detail::sequence *, const smart_library & lib, Args...args) : _lib(lib), _data(make_data(lib, static_cast(args)...)), _is_allocating(false), _size(0), - _ti(lib->get_type_info()) + _ti(lib.get_type_info()) { } template template -imported_class::imported_class(detail::sequence *, const boost::shared_ptr & lib, std::size_t size, Args...args) +imported_class::imported_class(detail::sequence *, const smart_library & lib, std::size_t size, Args...args) : _lib(lib), _data(make_data(lib, size, static_cast(args)...)), _is_allocating(true), _size(size), - _ti(lib->get_type_info()) + _ti(lib.get_type_info()) { } template -inline imported_class boost::dll::experimental::imported_class::copy() +template +imported_class::imported_class(detail::sequence *, smart_library && lib, Args...args) + : _lib(boost::move(lib)), + _data(make_data(lib, static_cast(args)...)), + _is_allocating(false), + _size(0), + _ti(lib.get_type_info()) +{ + +} + +template +template +imported_class::imported_class(detail::sequence *, smart_library && lib, std::size_t size, Args...args) + : _lib(boost::move(lib)), + _data(make_data(lib, size, static_cast(args)...)), + _is_allocating(true), + _size(size), + _ti(lib.get_type_info()) +{ + +} + +template +inline imported_class boost::dll::experimental::imported_class::copy() const { if (this->_is_allocating) return imported_class::template make(_lib, *_data); @@ -310,36 +384,170 @@ inline void boost::dll::experimental::imported_class::move_assign(imported_cl this->call("operator=")(static_cast(*lhs._data)); } + + +/*! +* Returns an instance of \ref imported_class which allows to call or import more functions. +* It takes a copy of the smart_libray, so no added type_aliases will be visible, +* for the object. +* +* Few compilers do implement an allocating constructor, which allows the construction +* of the class without knowing the size. That is not portable, so the actual size of the class +* shall always be provided. +* +* \b Example: +* +* \code +* auto import_class(lib, "class_name", 20, "param1", 42); +* \endcode +* +* In this example we construct an instance of the class "class_name" with the size 20, which has "type_alias" as an alias, +* through a constructor which takes a const-ref of std::string and an std::size_t parameter. +* +* \tparam T Class type or alias +* \tparam Args Constructor argument list. +* \param lib Path to shared library or shared library to load function from. +* \param name Null-terminated C or C++ mangled name of the function to import. Can handle std::string, char*, const char*. +* \param mode An mode that will be used on library load. +* +* \return class object. +* +* \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded. +* Overload that accepts path also throws std::bad_alloc in case of insufficient memory. +*/ template imported_class -import_class(const boost::shared_ptr& lib, Args...args) +import_class(const smart_library& lib_, std::size_t size, Args...args) +{ + smart_library lib(lib_); + + return imported_class::template make(boost::move(lib), size, static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(const smart_library& lib_, Args...args) +{ + smart_library lib(lib_); + return imported_class::template make(boost::move(lib), static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(const smart_library& lib_, const std::string & alias_name, Args...args) +{ + smart_library lib(lib_); + lib.add_type_alias(alias_name); + return imported_class::template make(boost::move(lib), static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(const smart_library& lib_, std::size_t size, const std::string & alias_name, Args...args) +{ + smart_library lib(lib_); + + lib.add_type_alias(alias_name); + return imported_class::template make(boost::move(lib), size, static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(const smart_library& lib_, const std::string & alias_name, std::size_t size, Args...args) +{ + smart_library lib(lib_); + + lib.add_type_alias(alias_name); + return imported_class::template make(boost::move(lib), size, static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(smart_library && lib, Args...args) +{ + return imported_class::template make(boost::move(lib), static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(smart_library && lib, const std::string & alias_name, Args...args) +{ + lib.add_type_alias(alias_name); + return imported_class::template make(boost::move(lib), static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(smart_library && lib, std::size_t size, Args...args) +{ + return imported_class::template make(boost::move(lib), size, static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(smart_library && lib, std::size_t size, const std::string & alias_name, Args...args) +{ + lib.add_type_alias(alias_name); + return imported_class::template make(boost::move(lib), size, static_cast(args)...); +} + +//! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) +template imported_class +import_class(smart_library && lib, const std::string & alias_name, std::size_t size, Args...args) +{ + lib.add_type_alias(alias_name); + return imported_class::template make(boost::move(lib), size, static_cast(args)...); +} + + + +/*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) + * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. + */ + +template imported_class +import_class(smart_library & lib, Args...args) { return imported_class::template make(lib, static_cast(args)...); } + +/*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) + * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. + */ template imported_class -import_class(const boost::shared_ptr& lib, const std::string & alias_name, Args...args) +import_class(smart_library & lib, const std::string & alias_name, Args...args) { - lib->add_type_alias(alias_name); + lib.add_type_alias(alias_name); return imported_class::template make(lib, static_cast(args)...); } + +/*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) + * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. + */ template imported_class -import_class(const boost::shared_ptr& lib, std::size_t size, Args...args) +import_class(smart_library & lib, std::size_t size, Args...args) { return imported_class::template make(lib, size, static_cast(args)...); } -template imported_class -import_class(const boost::shared_ptr& lib, std::size_t size, const std::string & alias_name, Args...args) -{ - lib->add_type_alias(alias_name); - return imported_class::template make(lib, size, static_cast(args)...); -} +/*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) + * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. + */ template imported_class -import_class(const boost::shared_ptr& lib, const std::string & alias_name, std::size_t size, Args...args) +import_class(smart_library & lib, std::size_t size, const std::string & alias_name, Args...args) { - lib->add_type_alias(alias_name); + lib.add_type_alias(alias_name); return imported_class::template make(lib, size, static_cast(args)...); } +/*! \overload boost::dll::import_class(const smart_library& lib, std::size_t, Args...) + * \note This function does add the type alias to the \ref boost::dll::experimental::smart_library. + */ +template imported_class +import_class(smart_library & lib, const std::string & alias_name, std::size_t size, Args...args) +{ + lib.add_type_alias(alias_name); + return imported_class::template make(lib, size, static_cast(args)...); +} } } diff --git a/include/boost/dll/import_mangled.hpp b/include/boost/dll/import_mangled.hpp index 47dad53..d75f9fc 100644 --- a/include/boost/dll/import_mangled.hpp +++ b/include/boost/dll/import_mangled.hpp @@ -37,7 +37,7 @@ class mangled_library_function { boost::shared_ptr> f_; public: - inline mangled_library_function(const boost::shared_ptr& lib, Ts*... func_ptr) BOOST_NOEXCEPT + inline mangled_library_function(const boost::shared_ptr& lib, Ts*... func_ptr) BOOST_NOEXCEPT : f_(lib, new function_tuple(func_ptr...)) {} @@ -69,7 +69,7 @@ class mangled_library_mem_fn> { boost::shared_ptr f_; public: - inline mangled_library_mem_fn(const boost::shared_ptr& lib, + inline mangled_library_mem_fn(const boost::shared_ptr& lib, typename Ts::mem_fn... func_ptr) BOOST_NOEXCEPT : f_(lib, new call_tuple_t(func_ptr...)) {} @@ -99,10 +99,12 @@ struct mangled_import_type, true,false,false> //is function { typedef boost::dll::experimental::detail::mangled_library_function type; static type make( - const boost::shared_ptr& p, + const boost::dll::experimental::smart_library& p, const std::string& name) { - return type(p, boost::addressof(p->get_function(name))...); + return type( + boost::make_shared(p.shared_lib()), + boost::addressof(p.get_function(name))...); } }; @@ -115,15 +117,16 @@ struct mangled_import_type, false, true, false> //is me template static type make_impl( - const boost::shared_ptr& p, + const boost::dll::experimental::smart_library& p, const std::string & name, sequence * ) { - return type(p, p->get_mem_fn(name)...); + return type(boost::make_shared(p.shared_lib()), + p.get_mem_fn(name)...); } static type make( - const boost::shared_ptr& p, + const boost::dll::experimental::smart_library& p, const std::string& name) { return make_impl(p, name, static_cast(nullptr)); @@ -137,10 +140,12 @@ struct mangled_import_type, false, false, true> //is variable typedef boost::shared_ptr type; static type make( - const boost::shared_ptr& p, + const boost::dll::experimental::smart_library& p, const std::string& name) { - return type(p, boost::addressof(p->get_variable(name))); + return type( + boost::make_shared(p.shared_lib()), + boost::addressof(p.get_variable(name))); } }; @@ -219,8 +224,7 @@ BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const boost::filesystem::pat typedef typename boost::dll::experimental::detail::mangled_import_type< boost::dll::experimental::detail::sequence> type; - boost::shared_ptr p = - boost::make_shared(lib, mode); + boost::dll::experimental::smart_library p(lib, mode); //the load return type::make(p, name); } @@ -240,8 +244,7 @@ template BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(const smart_library& lib, const char* name) { typedef typename boost::dll::experimental::detail::mangled_import_type> type; - boost::shared_ptr p = boost::make_shared(lib); - return type::make(p, name); + return type::make(lib, name); } //! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode) @@ -255,10 +258,7 @@ template BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(BOOST_RV_REF(smart_library) lib, const char* name) { typedef typename boost::dll::experimental::detail::mangled_import_type> type; - boost::shared_ptr p = boost::make_shared( - boost::move(lib) - ); - return type::make(p, name); + return type::make(lib, name); } //! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode) @@ -287,9 +287,8 @@ template BOOST_DLL_MANGLED_IMPORT_RESULT_TYPE import_mangled(BOOST_RV_REF(shared_library) lib, const char* name) { typedef typename boost::dll::experimental::detail::mangled_import_type> type; - boost::shared_ptr p = boost::make_shared( - boost::move(lib) - ); + boost::dll::experimental::smart_library p(boost::move(lib)); + return type::make(p, name); } diff --git a/include/boost/dll/smart_library.hpp b/include/boost/dll/smart_library.hpp index 77e7a80..358191b 100644 --- a/include/boost/dll/smart_library.hpp +++ b/include/boost/dll/smart_library.hpp @@ -125,7 +125,7 @@ public: * \throw Nothing. */ smart_library(BOOST_RV_REF(smart_library) lib) BOOST_NOEXCEPT - : _lib(boost::move(static_cast(lib._lib))), _storage(boost::move(lib._storage)) + : _lib(boost::move(lib._lib)), _storage(boost::move(lib._storage)) {} /*! @@ -202,7 +202,7 @@ public: * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded. */ template - T& get_variable(const std::string &name) { + T& get_variable(const std::string &name) const { return _lib.get(_storage.get_variable(name)); } @@ -228,7 +228,7 @@ public: * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded. */ template - Func& get_function(const std::string &name) { + Func& get_function(const std::string &name) const { return _lib.get(_storage.get_function(name)); } @@ -257,9 +257,9 @@ public: * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded. */ template - typename boost::dll::detail::get_mem_fn_type::mem_fn get_mem_fn(const std::string& name) { + typename boost::dll::detail::get_mem_fn_type::mem_fn get_mem_fn(const std::string& name) const { return _lib.get::mem_fn>( - _storage.get_mem_fn(name) + _storage.get_mem_fn(name) ); } @@ -280,7 +280,7 @@ public: * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded. */ template - constructor get_constructor() { + constructor get_constructor() const { return boost::dll::detail::load_ctor(_lib, _storage.get_constructor()); } @@ -302,7 +302,7 @@ public: * */ template - destructor get_destructor() { + destructor get_destructor() const { return boost::dll::detail::load_dtor(_lib, _storage.get_destructor()); } /*! @@ -323,7 +323,7 @@ public: * */ template - const std::type_info& get_type_info() + const std::type_info& get_type_info() const { return boost::dll::detail::load_type_info(_lib, _storage); } @@ -432,24 +432,24 @@ inline void swap(smart_library& lhs, smart_library& rhs) BOOST_NOEXCEPT { * @param name The name of the entity to import */ template -void get(smart_library& sm, const std::string &name); +void get(const smart_library& sm, const std::string &name); #endif template -T& get(smart_library& sm, const std::string &name, typename boost::enable_if,T>::type* = nullptr) +T& get(const smart_library& sm, const std::string &name, typename boost::enable_if,T>::type* = nullptr) { return sm.get_variable(name); } template -auto get(smart_library& sm, const std::string &name, typename boost::enable_if>::type* = nullptr) +auto get(const smart_library& sm, const std::string &name, typename boost::enable_if>::type* = nullptr) { return sm.get_function(name); } template -auto get(smart_library& sm, const std::string &name) -> typename detail::get_mem_fn_type::mem_fn +auto get(const smart_library& sm, const std::string &name) -> typename detail::get_mem_fn_type::mem_fn { return sm.get_mem_fn(name); } diff --git a/test/cpp_import_class_test.cpp b/test/cpp_import_class_test.cpp index cdbdaa1..6ddb190 100644 --- a/test/cpp_import_class_test.cpp +++ b/test/cpp_import_class_test.cpp @@ -6,6 +6,7 @@ // For more information, see http://www.boost.org + #include #if (__cplusplus >= 201402L) || (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14,0,0)) @@ -25,6 +26,7 @@ using namespace std; #include #include +#define L cout << __LINE__ << endl; int main(int argc, char* argv[]) { @@ -35,12 +37,12 @@ int main(int argc, char* argv[]) BOOST_TEST(!pt.empty()); std::cout << "Library: " << pt << std::endl; - boost::shared_ptr sm = boost::make_shared(pt); + smart_library sm(pt); auto static_val = import_mangled(sm, "some_space::some_class::value"); std::cout << "--------------------- Entry Points ------------------------\n" << std::endl; - for (auto &s : sm->symbol_storage().get_storage()) + for (auto &s : sm.symbol_storage().get_storage()) std::cout << s.demangled << std::endl; std::cout << "-----------------------------------------------------------\n\n" << std::endl; @@ -52,31 +54,30 @@ int main(int argc, char* argv[]) auto unscoped_var = import_mangled(sm, "unscoped_var"); std::size_t type_size = *import_mangled(sm, "some_space::size_of_some_class"); - { #if defined(BOOST_MSVC) || defined(BOOST_MSVC_FULL_VER) - class override_class{}; - auto cl = import_class(sm, "some_space::some_class", type_size, 42); + class override_class{}; + auto cl = import_class(sm, "some_space::some_class", type_size, 42); #else - auto cl = import_class(sm, "some_space::some_class", type_size, 42); + auto cl = import_class(sm, "some_space::some_class", type_size, 42); #endif - BOOST_TEST(!cl.is_copy_assignable()); - BOOST_TEST(!cl.is_copy_constructible()); + BOOST_TEST(!cl.is_copy_assignable()); + BOOST_TEST(!cl.is_copy_constructible()); - BOOST_TEST( cl.is_move_assignable()); - BOOST_TEST( cl.is_move_constructible()); + BOOST_TEST( cl.is_move_assignable()); + BOOST_TEST( cl.is_move_constructible()); - BOOST_TEST(*static_val == 42); + BOOST_TEST(*static_val == 42); - auto i = cl.call("get")(); - BOOST_TEST(i == 456); - cl.call("set")(42); - i = 0; - i = cl.call("get")(); - BOOST_TEST(i == 42); + auto i = cl.call("get")(); + BOOST_TEST(i == 456); + cl.call("set")(42); + i = 0; + i = cl.call("get")(); + BOOST_TEST(i == 42); - auto func = import_mangled< + auto func = import_mangled< override_class, double(double, double), int(int, int), volatile override_class, int(int, int), const volatile override_class, double(double, double)>(sm, "func");