diff --git a/include/boost/python/converter/registration.hpp b/include/boost/python/converter/registration.hpp index 0d85d1d7..b8a6326b 100644 --- a/include/boost/python/converter/registration.hpp +++ b/include/boost/python/converter/registration.hpp @@ -5,18 +5,19 @@ // to its suitability for any purpose. #ifndef REGISTRATION_DWA20011130_HPP # define REGISTRATION_DWA20011130_HPP -# include +# include # include # include -# include +# include +# include # ifdef BOOST_PYTHON_TRACE # include # endif namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT wrapper_base; -struct BOOST_PYTHON_EXPORT unwrapper_base; +struct BOOST_PYTHON_DECL wrapper_base; +struct BOOST_PYTHON_DECL unwrapper_base; // This class is really sort of a "templated namespace". It manages a // static data member which refers to the registry entry for T. This @@ -28,7 +29,7 @@ struct registration public: // member functions // Return a converter which can convert the given Python object to // T, or 0 if no such converter exists - static unwrapper_base* unwrapper(PyObject*); + static std::pair unwrapper(PyObject*); // Return a converter which can convert T to a Python object, or 0 // if no such converter exists @@ -61,7 +62,7 @@ inline registry::entry* registration::entry() } template -unwrapper_base* registration::unwrapper(PyObject* p) +std::pair registration::unwrapper(PyObject* p) { # ifdef BOOST_PYTHON_TRACE std::cout << "retrieving unwrapper for " << type_id() << std::endl; diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index 30eeba8d..2023a732 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -7,20 +7,21 @@ # define REGISTRY_DWA20011127_HPP # include # include -# include +# include # include # include +# include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT wrapper_base; -struct BOOST_PYTHON_EXPORT unwrapper_base; +struct BOOST_PYTHON_DECL wrapper_base; +struct BOOST_PYTHON_DECL unwrapper_base; // This namespace acts as a sort of singleton namespace registry { // These are the elements stored in the registry - class BOOST_PYTHON_EXPORT entry + class BOOST_PYTHON_DECL entry { public: // member functions entry(); @@ -30,7 +31,7 @@ namespace registry // Python object from_python to the C++ type with which this // converter is associated in the registry, or 0 if no such // converter exists. - unwrapper_base* unwrapper(PyObject*) const; + std::pair unwrapper(PyObject*) const; // Return a converter appropriate for converting a C++ object // whose type this entry is associated with in the registry to a @@ -61,12 +62,12 @@ namespace registry converter::wrapper_base* m_wrapper; }; - BOOST_PYTHON_EXPORT entry* find(type_id_t); + BOOST_PYTHON_DECL entry* find(type_id_t); - BOOST_PYTHON_EXPORT void insert(wrapper_base& x); - BOOST_PYTHON_EXPORT void insert(unwrapper_base& x); - BOOST_PYTHON_EXPORT void remove(wrapper_base& x); - BOOST_PYTHON_EXPORT void remove(unwrapper_base& x); + BOOST_PYTHON_DECL void insert(wrapper_base& x); + BOOST_PYTHON_DECL void insert(unwrapper_base& x); + BOOST_PYTHON_DECL void remove(wrapper_base& x); + BOOST_PYTHON_DECL void remove(unwrapper_base& x); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp index 4a2ea04c..ffd0f081 100644 --- a/include/boost/python/converter/unwrap.hpp +++ b/include/boost/python/converter/unwrap.hpp @@ -12,22 +12,28 @@ # include # include # include -# include +# include +# include namespace boost { namespace python { namespace converter { template struct unwrapper; -struct BOOST_PYTHON_EXPORT body; +struct BOOST_PYTHON_DECL body; -struct BOOST_PYTHON_EXPORT unwrap_base : handle +struct BOOST_PYTHON_DECL unwrap_base : handle { public: // member functions - inline unwrap_base(PyObject* source, body*, handle& prev); - inline unwrap_base(PyObject* source, body*); + inline unwrap_base(PyObject* source, std::pair, handle& prev); + inline unwrap_base(PyObject* source, std::pair); inline PyObject* source() const; - + + protected: + inline PyObject*& source(); + inline void* data() const; + private: // data members PyObject* m_source; + void* m_data; }; // These converters will be used by the function wrappers. They don't @@ -47,15 +53,7 @@ struct unwrap_more_ : unwrap_base // this constructor is only for the use of unwrap_ unwrap_more_(PyObject* source); - private: // helper functions - // Return the unwrapper which will convert the given Python object - // to T, or 0 if no such converter exists - static unwrapper_base* lookup(PyObject*); - private: - // unspecified storage which may be allocated by the unwrapper to - // do value conversions. - mutable void* m_storage; typedef typename unwrapper_select::type unwrapper_t; }; @@ -78,9 +76,9 @@ struct unwrap_more_ return source(); } - bool convertible(PyObject*) const + void* can_convert(PyObject*) const { - return true; + return &m_unwrapper; } protected: // constructor @@ -91,7 +89,7 @@ struct unwrap_more_ { } private: - static BOOST_PYTHON_EXPORT unwrapper_base* m_unwrapper; + static BOOST_PYTHON_DECL std::pair m_unwrapper; }; template @@ -104,42 +102,47 @@ struct unwrap_ : unwrap_more_ // // implementations // -inline unwrap_base::unwrap_base(PyObject* source, body* body, handle& prev) - : handle(body, prev) +inline unwrap_base::unwrap_base( + PyObject* source, std::pair unwrapper, handle& prev) + : handle(unwrapper.first, prev) , m_source(source) + , m_data(unwrapper.second) { } -inline unwrap_base::unwrap_base(PyObject* source, body* body) - : handle(body) +inline unwrap_base::unwrap_base(PyObject* source, std::pair unwrapper) + : handle(unwrapper.first) , m_source(source) + , m_data(unwrapper.second) { } +inline void* unwrap_base::data() const +{ + return m_data; +} + inline PyObject* unwrap_base::source() const { return m_source; } -template -inline unwrapper_base* unwrap_more_::lookup(PyObject* source) +inline PyObject*& unwrap_base::source() { - // Find the converters registered for T and get a unwrapper - // appropriate for the source object - return registration::unwrapper(source); + return m_source; } template unwrap_more_::unwrap_more_(PyObject* source, handle& prev) - : unwrap_base(source, lookup(source), prev) - , m_storage(0) + : unwrap_base(source, + registration::unwrapper(source), + prev) { } template unwrap_more_::unwrap_more_(PyObject* source) - : unwrap_base(source, lookup(source)) - , m_storage(0) + : unwrap_base(source, registration::unwrapper(source)) { } @@ -153,7 +156,7 @@ template T unwrap_more_::operator*() { return static_cast*>( - get_body())->convert(this->m_source, this->m_storage); + get_body())->convert(this->source(), this->data(), boost::type()); } template diff --git a/include/boost/python/converter/unwrapper.hpp b/include/boost/python/converter/unwrapper.hpp index a30ff522..7f0609cf 100644 --- a/include/boost/python/converter/unwrapper.hpp +++ b/include/boost/python/converter/unwrapper.hpp @@ -9,6 +9,7 @@ # include # include # include +# include namespace boost { namespace python { namespace converter { @@ -21,13 +22,7 @@ struct unwrapper : unwrapper_base public: unwrapper(); - T do_conversion(unwrap_more_ const* handle) const; - - private: - virtual T convert(PyObject*, void*&) const = 0; - - private: // body required interface implementation - void destroy_handle(handle*) const {} + virtual T convert(PyObject*, void* data, boost::type) const = 0; }; // @@ -39,15 +34,6 @@ unwrapper::unwrapper() { } -// We could think about making this virtual in an effort to get its -// code generated in the module where the unwrapper is defined, but -// it's not clear that it's a good tradeoff. -template -T unwrapper::do_conversion(unwrap_more_ const* handle) const -{ - return convert(handle->source(), handle->m_storage); -} - }}} // namespace boost::python::converter #endif // UNWRAPPER_DWA2001127_HPP diff --git a/include/boost/python/converter/unwrapper_base.hpp b/include/boost/python/converter/unwrapper_base.hpp index 54e2e54c..ea437eb2 100644 --- a/include/boost/python/converter/unwrapper_base.hpp +++ b/include/boost/python/converter/unwrapper_base.hpp @@ -8,16 +8,27 @@ # include # include # include -# include +# include namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_EXPORT unwrapper_base : body +struct BOOST_PYTHON_DECL unwrapper_base : body { public: unwrapper_base(type_id_t); // registers ~unwrapper_base(); // unregisters - virtual bool convertible(PyObject*) const = 0; + + // Must return non-null iff the conversion will be successful. Any + // non-null pointer is acceptable, and will be passed on to the + // convert() function, so useful data can be stored there. + virtual void* can_convert(PyObject*) const = 0; + + protected: + // this is an arbitrary non-null pointer you can use to indicate success + static void* const non_null; + + private: // body required interface implementation + void destroy_handle(handle*) const {} }; }}} // namespace boost::python::converter