diff options
Diffstat (limited to 'boost/dll/detail/ctor_dtor.hpp')
-rw-r--r-- | boost/dll/detail/ctor_dtor.hpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/boost/dll/detail/ctor_dtor.hpp b/boost/dll/detail/ctor_dtor.hpp new file mode 100644 index 0000000000..5950d9e60a --- /dev/null +++ b/boost/dll/detail/ctor_dtor.hpp @@ -0,0 +1,176 @@ +// Copyright 2016 Klemens Morgenstern, Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#ifndef INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ +#define INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ + +#include <boost/config.hpp> +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include <boost/dll/detail/aggressive_ptr_cast.hpp> +#include <boost/dll/detail/get_mem_fn_type.hpp> + +#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER) +# include <boost/dll/detail/demangling/msvc.hpp> +#else +# include <boost/dll/detail/demangling/itanium.hpp> +#endif + +namespace boost { namespace dll { namespace detail { + +/*! + * This class stores a constructor. + * + * In some compilers there are several constructors in code, which may include an allocating one. + * This can be used if the imported class shall be put on the heap, which is why the class provied both types. + */ +template<typename Signature> +struct constructor; + +template<typename Class, typename ...Args> +struct constructor<Class(Args...)> { + typedef typename detail::get_mem_fn_type<Class, void(Args...)>::mem_fn standard_t; + typedef Class*(*allocating_t)(Args...); + + + //! The standard, i.e. not allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_standard instead. + standard_t standard; + //! The allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_allocating instead. + allocating_t allocating; + + //! Call the standard contructor + void call_standard (Class * const ptr, Args...args){ (ptr->*standard)(static_cast<Args>(args)...); } + + //! Call the deleting destructor + Class * call_allocating(Args...args){ return allocating(static_cast<Args>(args)...); } + + + //! True if a allocating constructor could be loaded. + bool has_allocating() const { return allocating != nullptr; } + + //! False if neither the allocating nor the standard constructor is available. + bool is_empty() const { return !((allocating == nullptr) && (standard != nullptr)) ; } + + constructor() = delete; + constructor(const constructor &) = default; + + explicit constructor(standard_t standard, allocating_t allocating = nullptr) + : standard(standard) + , allocating(allocating) + {} +}; + + + +template <typename Class> +struct destructor { +#if !defined(BOOST_MSVC) && !defined(BOOST_MSVC_VER) + typedef void( *type)(Class* const); +#elif !defined(_WIN64) + typedef void(__thiscall * type)(Class* const); +#else + typedef void(__cdecl * type)(Class* const); +#endif + + typedef type standard_t; + typedef type deleting_t; + + //! The standard, i.e. not deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_standard instead. + standard_t standard; + //! The deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_deallocating instead. + deleting_t deleting; + + //! Call the standard contructor + void call_standard(Class * const ptr){ standard(ptr); } + + //! Call the deleting destructor + void call_deleting(Class * const ptr){ deleting(ptr); } + + //! True if a deleting destructor could be loaded. + bool has_deleting() const { return deleting != nullptr; } + + //! False if neither the deleting nor the standard destructor is available. + bool is_empty() const { return !((deleting == nullptr) && (standard != nullptr)) ; } + destructor() = delete; + + //! Copy destructor. + destructor(const destructor &) = default; + + //! Construct it from both the standard destructor and the allocating destructor + explicit destructor(const standard_t &standard, const deleting_t &deleting = nullptr) + : standard(standard) + , deleting(deleting) + {} +}; + +#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER) +template<typename Signature, typename Lib> +constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) { + typedef typename constructor<Signature>::standard_t standard_t; + standard_t ctor = lib.template get<standard_t>(ct); + return constructor<Signature>(ctor); +} + +template<typename Class, typename Lib> +destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) { + typedef typename destructor<Class>::standard_t standard_t; + standard_t dtor = &lib.template get< typename boost::remove_pointer<standard_t>::type >(dt); + return destructor<Class>(dtor); +} + +#else + +template<typename Signature, typename Lib> +constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) { + typedef typename constructor<Signature>::standard_t stand; + typedef typename constructor<Signature>::allocating_t alloc; + + stand s = nullptr; + alloc a = nullptr; + + //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor + + if (!ct.C1.empty()) { + s = lib.template get<stand>(ct.C1); + } + + if (!ct.C3.empty()) { + a = lib.template get<alloc>(ct.C3); + } + + return constructor<Signature>(s,a); +} + +template<typename Class, typename Lib> +destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) { + typedef typename destructor<Class>::standard_t stand; + typedef typename destructor<Class>::deleting_t delet; + + stand s = nullptr; + delet d = nullptr; + + //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor + if (!dt.D1.empty()) { + s = &lib.template get< typename boost::remove_pointer<stand>::type >(dt.D1); + } + + if (!dt.D0.empty()) { + d = &lib.template get< typename boost::remove_pointer<delet>::type >(dt.D0); + } + + return destructor<Class>(s,d); + +} + +#endif + +}}} // namespace boost::dll::detail + +#endif /* INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ */ |