1010# include < boost/python/converter/to_python_function.hpp>
1111# include < boost/python/converter/pointee_to_python_function.hpp>
1212# include < boost/python/converter/arg_to_python_base.hpp>
13+ # include < boost/python/converter/object_manager.hpp>
1314# include < boost/python/to_python_indirect.hpp>
15+ # include < boost/type_traits/cv_traits.hpp>
16+ # include < boost/python/detail/convertible.hpp>
17+ # include < boost/python/base_type_traits.hpp>
1418// Bring in specializations
1519# include < boost/python/converter/builtin_converters.hpp>
1620
@@ -51,9 +55,27 @@ namespace detail
5155 static PyObject* get_object (Ptr p);
5256 };
5357
58+ // Convert types that manage a Python object to_python
59+ template <class T >
60+ struct object_manager_arg_to_python
61+ {
62+ object_manager_arg_to_python (T const & x) : m_src(x) {}
63+
64+ PyObject* get () const
65+ {
66+ return python::upcast<PyObject>(converter::get_managed_object (m_src));
67+ }
68+
69+ private:
70+ T const & m_src;
71+ };
72+
5473 template <class T >
5574 struct select_arg_to_python
5675 {
76+ BOOST_STATIC_CONSTANT (
77+ bool , manager = is_object_manager<T>::value);
78+
5779 BOOST_STATIC_CONSTANT (
5880 bool , ptr = is_pointer<T>::value);
5981
@@ -67,15 +89,19 @@ namespace detail
6789 typedef typename unwrap_pointer<T>::type unwrapped_ptr;
6890
6991 typedef typename mpl::select_type<
70- ptr
71- , pointer_deep_arg_to_python <T>
92+ manager
93+ , object_manager_arg_to_python <T>
7294 , typename mpl::select_type<
73- ptr_wrapper
74- , pointer_shallow_arg_to_python<unwrapped_ptr >
95+ ptr
96+ , pointer_deep_arg_to_python<T >
7597 , typename mpl::select_type<
76- ref_wrapper
77- , reference_arg_to_python<unwrapped_referent>
78- , value_arg_to_python<T>
98+ ptr_wrapper
99+ , pointer_shallow_arg_to_python<unwrapped_ptr>
100+ , typename mpl::select_type<
101+ ref_wrapper
102+ , reference_arg_to_python<unwrapped_referent>
103+ , value_arg_to_python<T>
104+ >::type
79105 >::type
80106 >::type
81107 >::type type;
@@ -108,6 +134,39 @@ struct arg_to_python
108134//
109135namespace detail
110136{
137+ // reject_raw_object_ptr -- cause a compile-time error if the user
138+ // should pass a raw Python object pointer
139+ using python::detail::yes_convertible;
140+ using python::detail::no_convertible;
141+ using python::detail::unspecialized;
142+
143+ template <class T > struct cannot_convert_raw_PyObject ;
144+
145+ template <class T , class Convertibility >
146+ struct reject_raw_object_helper
147+ {
148+ static void error (Convertibility)
149+ {
150+ cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead ();
151+ }
152+ static void error (...) {}
153+ };
154+
155+ template <class T >
156+ inline void reject_raw_object_ptr (T*)
157+ {
158+ reject_raw_object_helper<T,yes_convertible>::error (
159+ python::detail::convertible<PyObject const volatile *>::check ((T*)0 ));
160+
161+ typedef typename remove_cv<T>::type value_type;
162+
163+ reject_raw_object_helper<T,no_convertible>::error (
164+ python::detail::convertible<unspecialized*>::check (
165+ (base_type_traits<value_type>*)0
166+ ));
167+ }
168+ // ---------
169+
111170 template <class T >
112171 inline value_arg_to_python<T>::value_arg_to_python(T const & x)
113172 : arg_to_python_base(&x, to_python_function<T>::value)
@@ -118,6 +177,7 @@ namespace detail
118177 inline pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr x)
119178 : arg_to_python_base(x, pointee_to_python_function<Ptr>::value)
120179 {
180+ detail::reject_raw_object_ptr ((Ptr)0 );
121181 }
122182
123183 template <class T >
@@ -131,14 +191,16 @@ namespace detail
131191
132192 template <class T >
133193 inline reference_arg_to_python<T>::reference_arg_to_python(T& x)
134- : handle<>(get_object(x))
194+ : handle<>(reference_arg_to_python<T>:: get_object(x))
135195 {
136196 }
137197
138198 template <class Ptr >
139199 inline pointer_shallow_arg_to_python<Ptr>::pointer_shallow_arg_to_python(Ptr x)
140- : handle<>(get_object(x))
141- {}
200+ : handle<>(pointer_shallow_arg_to_python<Ptr>::get_object(x))
201+ {
202+ detail::reject_raw_object_ptr ((Ptr)0 );
203+ }
142204
143205 template <class Ptr >
144206 inline PyObject* pointer_shallow_arg_to_python<Ptr>::get_object(Ptr x)
0 commit comments