1 // Copyright David Abrahams 2002. 2 // Copyright Stefan Seefeld 2016. 3 // Distributed under the Boost Software License, Version 1.0. (See 4 // accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef boost_python_converter_shared_ptr_from_python_hpp_ 8 #define boost_python_converter_shared_ptr_from_python_hpp_ 9 10 #include <boost/python/handle.hpp> 11 #include <boost/python/converter/shared_ptr_deleter.hpp> 12 #include <boost/python/converter/from_python.hpp> 13 #include <boost/python/converter/rvalue_from_python_data.hpp> 14 #include <boost/python/converter/registered.hpp> 15 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES 16 # include <boost/python/converter/pytype_function.hpp> 17 #endif 18 #include <boost/shared_ptr.hpp> 19 #include <memory> 20 21 namespace boost { namespace python { namespace converter { 22 23 template <class T, template <typename> class SP> 24 struct shared_ptr_from_python 25 { shared_ptr_from_pythonboost::python::converter::shared_ptr_from_python26 shared_ptr_from_python() 27 { 28 converter::registry::insert(&convertible, &construct, type_id<SP<T> >() 29 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES 30 , &converter::expected_from_python_type_direct<T>::get_pytype 31 #endif 32 ); 33 } 34 35 private: convertibleboost::python::converter::shared_ptr_from_python36 static void* convertible(PyObject* p) 37 { 38 if (p == Py_None) 39 return p; 40 41 return converter::get_lvalue_from_python(p, registered<T>::converters); 42 } 43 constructboost::python::converter::shared_ptr_from_python44 static void construct(PyObject* source, rvalue_from_python_stage1_data* data) 45 { 46 void* const storage = ((converter::rvalue_from_python_storage<SP<T> >*)data)->storage.bytes; 47 // Deal with the "None" case. 48 if (data->convertible == source) 49 new (storage) SP<T>(); 50 else 51 { 52 SP<void> hold_convertible_ref_count( 53 (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); 54 // use aliasing constructor 55 new (storage) SP<T>(hold_convertible_ref_count, 56 static_cast<T*>(data->convertible)); 57 } 58 59 data->convertible = storage; 60 } 61 }; 62 63 }}} // namespace boost::python::converter 64 65 #endif 66