1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
6 # define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
7 
8 # include <boost/python/detail/prefix.hpp>
9 # include <boost/python/detail/referent_storage.hpp>
10 # include <boost/python/detail/destroy.hpp>
11 # include <boost/python/detail/construct.hpp>
12 # include <boost/python/converter/object_manager.hpp>
13 # include <boost/python/detail/raw_pyobject.hpp>
14 # include <boost/python/tag.hpp>
15 
16 //
17 // arg_from_python converters for Python type wrappers, to be used as
18 // base classes for specializations.
19 //
20 namespace boost { namespace python { namespace converter {
21 
22 template <class T>
23 struct object_manager_value_arg_from_python
24 {
25     typedef T result_type;
26 
27     object_manager_value_arg_from_python(PyObject*);
28     bool convertible() const;
29     T operator()() const;
30  private:
31     PyObject* m_source;
32 };
33 
34 // Used for converting reference-to-object-manager arguments from
35 // python. The process used here is a little bit odd. Upon
36 // construction, we build the object manager object in the m_result
37 // object, *forcing* it to accept the source Python object by casting
38 // its pointer to detail::borrowed_reference. This is supposed to
39 // bypass any type checking of the source object. The convertible
40 // check then extracts the owned object and checks it. If the check
41 // fails, nothing else in the program ever gets to touch this strange
42 // "forced" object.
43 template <class Ref>
44 struct object_manager_ref_arg_from_python
45 {
46     typedef Ref result_type;
47 
48     object_manager_ref_arg_from_python(PyObject*);
49     bool convertible() const;
50     Ref operator()() const;
51     ~object_manager_ref_arg_from_python();
52  private:
53     typename python::detail::referent_storage<Ref>::type m_result;
54 };
55 
56 //
57 // implementations
58 //
59 
60 template <class T>
object_manager_value_arg_from_python(PyObject * x)61 inline object_manager_value_arg_from_python<T>::object_manager_value_arg_from_python(PyObject* x)
62     : m_source(x)
63 {
64 }
65 
66 template <class T>
convertible() const67 inline bool object_manager_value_arg_from_python<T>::convertible() const
68 {
69     return object_manager_traits<T>::check(m_source);
70 }
71 
72 template <class T>
operator ()() const73 inline T object_manager_value_arg_from_python<T>::operator()() const
74 {
75     return T(python::detail::borrowed_reference(m_source));
76 }
77 
78 template <class Ref>
object_manager_ref_arg_from_python(PyObject * x)79 inline object_manager_ref_arg_from_python<Ref>::object_manager_ref_arg_from_python(PyObject* x)
80 {
81 # if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243
82     // needed for warning suppression
83     python::detail::borrowed_reference x_ = python::detail::borrowed_reference(x);
84     python::detail::construct_referent<Ref>(&m_result.bytes, x_);
85 # else
86     python::detail::construct_referent<Ref>(&m_result.bytes, (python::detail::borrowed_reference)x);
87 # endif
88 }
89 
90 template <class Ref>
~object_manager_ref_arg_from_python()91 inline object_manager_ref_arg_from_python<Ref>::~object_manager_ref_arg_from_python()
92 {
93     python::detail::destroy_referent<Ref>(this->m_result.bytes);
94 }
95 
96 namespace detail
97 {
98   template <class T>
object_manager_ref_check(T const & x)99   inline bool object_manager_ref_check(T const& x)
100   {
101       return object_manager_traits<T>::check(get_managed_object(x, tag));
102   }
103 }
104 
105 template <class Ref>
convertible() const106 inline bool object_manager_ref_arg_from_python<Ref>::convertible() const
107 {
108     return detail::object_manager_ref_check(
109         python::detail::void_ptr_to_reference(this->m_result.bytes, (Ref(*)())0));
110 }
111 
112 template <class Ref>
operator ()() const113 inline Ref object_manager_ref_arg_from_python<Ref>::operator()() const
114 {
115     return python::detail::void_ptr_to_reference(
116         this->m_result.bytes, (Ref(*)())0);
117 }
118 
119 }}} // namespace boost::python::converter
120 
121 #endif // OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
122