|
| 1 | +// Copyright David Abrahams 2002. Permission to copy, use, |
| 2 | +// modify, sell and distribute this software is granted provided this |
| 3 | +// copyright notice appears in all copies. This software is provided |
| 4 | +// "as is" without express or implied warranty, and with no claim as |
| 5 | +// to its suitability for any purpose. |
| 6 | +#ifndef TO_PYTHON_INDIRECT_DWA200221_HPP |
| 7 | +# define TO_PYTHON_INDIRECT_DWA200221_HPP |
| 8 | + |
| 9 | +# include <boost/type_traits/object_traits.hpp> |
| 10 | +# include <boost/python/object/pointer_holder.hpp> |
| 11 | +# include <boost/python/object/class_object.hpp> |
| 12 | +# include <boost/python/detail/unwind_type.hpp> |
| 13 | +# include <memory> |
| 14 | + |
| 15 | +namespace boost { namespace python { |
| 16 | + |
| 17 | +template <class T, class HolderGenerator> |
| 18 | +struct to_python_indirect |
| 19 | +{ |
| 20 | + static bool convertible(); |
| 21 | + PyObject* operator()(T ptr) const; |
| 22 | + private: |
| 23 | + static PyTypeObject* type(); |
| 24 | +}; |
| 25 | + |
| 26 | +// |
| 27 | +// implementations |
| 28 | +// |
| 29 | +namespace detail |
| 30 | +{ |
| 31 | + struct make_owning_holder |
| 32 | + { |
| 33 | + typedef objects::instance_holder* result_type; |
| 34 | + template <class T> |
| 35 | + static result_type execute(T* p) |
| 36 | + { |
| 37 | + return new objects::pointer_holder<std::auto_ptr<T>, T>( |
| 38 | + std::auto_ptr<T>(p)); |
| 39 | + } |
| 40 | + }; |
| 41 | + |
| 42 | + struct make_reference_holder |
| 43 | + { |
| 44 | + typedef objects::instance_holder* result_type; |
| 45 | + template <class T> |
| 46 | + static result_type execute(T* p) |
| 47 | + { |
| 48 | + return new objects::pointer_holder<T*, T>(p); |
| 49 | + } |
| 50 | + }; |
| 51 | + |
| 52 | + struct get_pointer_class |
| 53 | + { |
| 54 | + typedef PyTypeObject* result_type; |
| 55 | + template <class T> |
| 56 | + static result_type execute(T* p) |
| 57 | + { |
| 58 | + BOOST_STATIC_ASSERT(is_class<T>::value); |
| 59 | + return python::objects::class_object<T>::reference; |
| 60 | + } |
| 61 | + }; |
| 62 | +} |
| 63 | + |
| 64 | +template <class T, class HolderGenerator> |
| 65 | +inline bool to_python_indirect<T,HolderGenerator>::convertible() |
| 66 | +{ |
| 67 | + return type() != 0; |
| 68 | +} |
| 69 | + |
| 70 | +template <class T, class HolderGenerator> |
| 71 | +inline PyObject* to_python_indirect<T,HolderGenerator>::operator()(T x) const |
| 72 | +{ |
| 73 | + PyObject* raw_result = type()->tp_alloc(type(), 0); |
| 74 | + |
| 75 | + if (raw_result == 0) |
| 76 | + return 0; |
| 77 | + |
| 78 | + // Everything's OK; Bypass NULL checks but guard against |
| 79 | + // exceptions. |
| 80 | + ref result(raw_result, ref::allow_null()); |
| 81 | + |
| 82 | + // Build a value_holder to contain the object using the copy |
| 83 | + // constructor |
| 84 | + objects::instance_holder* p = |
| 85 | + detail::unwind_type<HolderGenerator>(x); |
| 86 | + |
| 87 | + // Install it in the instance |
| 88 | + p->install(raw_result); |
| 89 | + |
| 90 | + // Return the new result |
| 91 | + return result.release(); |
| 92 | +} |
| 93 | + |
| 94 | +template <class T, class HolderGenerator> |
| 95 | +inline PyTypeObject* to_python_indirect<T,HolderGenerator>::type() |
| 96 | +{ |
| 97 | + return detail::unwind_type<detail::get_pointer_class,T>(); |
| 98 | +} |
| 99 | + |
| 100 | +}} // namespace boost::python |
| 101 | + |
| 102 | +#endif // TO_PYTHON_INDIRECT_DWA200221_HPP |
0 commit comments