Skip to content

Commit 244e0fa

Browse files
committed
More converter centralization
[SVN r14487]
1 parent 134bc44 commit 244e0fa

File tree

13 files changed

+370
-241
lines changed

13 files changed

+370
-241
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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 ALWAYS_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
7+
# define ALWAYS_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
8+
9+
# include <boost/config.hpp>
10+
11+
namespace boost { namespace python { namespace converter {
12+
13+
// Derive specializations of extract_object_manager from this when the
14+
// object manager is indiscriminate about the Python objects it manages
15+
struct always_extract_object_manager
16+
{
17+
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
18+
static inline bool check(PyObject* x);
19+
};
20+
21+
// Provide a forward declaration as a convenience for clients, who all
22+
// need it.
23+
template <class T> struct extract_object_manager;
24+
25+
//
26+
// implementations
27+
//
28+
inline bool always_extract_object_manager::check(PyObject* x)
29+
{
30+
return true;
31+
}
32+
33+
}}} // namespace boost::python::converter
34+
35+
#endif // ALWAYS_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP

include/boost/python/converter/arg_from_python.hpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# include <boost/python/detail/void_ptr.hpp>
2020
# include <boost/python/back_reference.hpp>
2121
# include <boost/python/detail/referent_storage.hpp>
22+
# include <boost/python/converter/obj_mgr_arg_from_python.hpp>
2223

2324
namespace boost { namespace python
2425
{
@@ -139,6 +140,12 @@ struct back_reference_arg_from_python
139140
template <class T>
140141
struct select_arg_from_python
141142
{
143+
BOOST_STATIC_CONSTANT(
144+
bool, obj_mgr = is_object_manager<T>::value);
145+
146+
BOOST_STATIC_CONSTANT(
147+
bool, obj_mgr_ref = is_reference_to_object_manager<T>::value);
148+
142149
BOOST_STATIC_CONSTANT(
143150
bool, ptr = is_pointer<T>::value);
144151

@@ -159,22 +166,30 @@ struct select_arg_from_python
159166
boost::python::is_back_reference<T>::value);
160167

161168
typedef typename mpl::select_type<
162-
ptr
163-
, pointer_arg_from_python<T>
164-
, typename mpl::select_type<
165-
ptr_cref
166-
, pointer_cref_arg_from_python<T>
167-
, typename mpl::select_type<
168-
ref
169-
, reference_arg_from_python<T>
170-
, typename mpl::select_type<
171-
back_ref
172-
, back_reference_arg_from_python<T>
173-
, arg_rvalue_from_python<T>
174-
>::type
175-
>::type
169+
obj_mgr
170+
, object_manager_value_arg_from_python<T>
171+
, mpl::select_type<
172+
obj_mgr_ref
173+
, object_manager_ref_arg_from_python<T>
174+
, mpl::select_type<
175+
ptr
176+
, pointer_arg_from_python<T>
177+
, typename mpl::select_type<
178+
ptr_cref
179+
, pointer_cref_arg_from_python<T>
180+
, typename mpl::select_type<
181+
ref
182+
, reference_arg_from_python<T>
183+
, typename mpl::select_type<
184+
back_ref
185+
, back_reference_arg_from_python<T>
186+
, arg_rvalue_from_python<T>
187+
>::type
188+
>::type
189+
>::type
190+
>::type
176191
>::type
177-
>::type type;
192+
>::type type;
178193
};
179194

180195
// ==================
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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 OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
7+
# define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
8+
9+
# include <boost/python/detail/wrap_python.hpp>
10+
# include <boost/python/detail/referent_storage.hpp>
11+
# include <boost/python/detail/destroy.hpp>
12+
# include <boost/python/detail/construct.hpp>
13+
# include <boost/python/converter/object_manager.hpp>
14+
15+
//
16+
// arg_from_python converters for Python type wrappers, to be used as
17+
// base classes for specializations.
18+
//
19+
namespace boost { namespace python { namespace converter {
20+
21+
template <class T>
22+
struct object_manager_value_arg_from_python
23+
{
24+
typedef T result_type;
25+
26+
object_manager_value_arg_from_python(PyObject*);
27+
bool convertible() const;
28+
T operator()(PyObject*) const;
29+
private:
30+
PyObject* m_source;
31+
};
32+
33+
template <class Ref>
34+
struct object_manager_ref_arg_from_python
35+
{
36+
typedef Ref result_type;
37+
38+
object_manager_ref_arg_from_python(PyObject*);
39+
bool convertible() const;
40+
Ref operator()(PyObject*) const;
41+
~object_manager_ref_arg_from_python();
42+
private:
43+
typename python::detail::referent_storage<Ref>::type m_result;
44+
};
45+
46+
//
47+
// implementations
48+
//
49+
50+
template <class T>
51+
inline object_manager_value_arg_from_python<T>::object_manager_value_arg_from_python(PyObject* x)
52+
: m_source(x)
53+
{
54+
}
55+
56+
template <class T>
57+
inline bool object_manager_value_arg_from_python<T>::convertible() const
58+
{
59+
return extract_object_manager<T>::check(m_source);
60+
}
61+
62+
template <class T>
63+
inline T object_manager_value_arg_from_python<T>::operator()(PyObject* x) const
64+
{
65+
return T(python::detail::borrowed_reference(x));
66+
}
67+
68+
template <class Ref>
69+
inline object_manager_ref_arg_from_python<Ref>::object_manager_ref_arg_from_python(PyObject* x)
70+
{
71+
python::detail::construct_referent<Ref>(&m_result.bytes, python::detail::borrowed_reference(x));
72+
}
73+
74+
template <class Ref>
75+
inline object_manager_ref_arg_from_python<Ref>::~object_manager_ref_arg_from_python()
76+
{
77+
python::detail::destroy_referent<Ref>(this->m_result.bytes);
78+
}
79+
80+
namespace detail
81+
{
82+
template <class T>
83+
inline bool object_manager_ref_check(T const& x)
84+
{
85+
return extract_object_manager<T>::check((get_managed_object)(x));
86+
}
87+
}
88+
89+
template <class Ref>
90+
inline bool object_manager_ref_arg_from_python<Ref>::convertible() const
91+
{
92+
return detail::object_manager_ref_check(
93+
python::detail::void_ptr_to_reference(this->m_result.bytes, (Ref(*)())0));
94+
}
95+
96+
template <class Ref>
97+
inline Ref object_manager_ref_arg_from_python<Ref>::operator()(PyObject*) const
98+
{
99+
return python::detail::void_ptr_to_reference(
100+
this->m_result.bytes, (Ref(*)())0);
101+
}
102+
103+
}}} // namespace boost::python::converter
104+
105+
#endif // OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP

include/boost/python/converter/object_manager.hpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,55 @@
1212
# include <boost/mpl/select_type.hpp>
1313
# include <boost/python/detail/indirect_traits.hpp>
1414

15-
namespace boost { namespace python { namespace api {
16-
17-
class object;
18-
15+
// Facilities for dealing with types which always manage Python
16+
// objects. Some examples are object, list, et. al. Different
17+
// to_python/from_python conversion rules apply here because in
18+
// contrast to other types which are typically embedded inside a
19+
// Python object, these are wrapped around a Python object. For most
20+
// object managers T, a C++ non-const T reference argument does not
21+
// imply the existence of a T lvalue embedded in the corresponding
22+
// Python argument, since mutating member functions on T actually only
23+
// modify the held Python object.
24+
//
25+
// Note also that handle<> does not qualify as an object manager because:
26+
// a. It might not manage a Python object (it can be null)
27+
// b. Mutating operations visible to users modify the handle<> itself.
28+
29+
namespace boost { namespace python { namespace api
30+
{
31+
class object; // forward declaration
1932
}}}
2033

2134
namespace boost { namespace python { namespace converter {
2235

36+
// Used to create object managers of type T, taking ownership of a
37+
// given PyObject*. Specializations X must satisfy the following,
38+
// where p is a non-null PyObject*:
39+
//
40+
// X::is_specialized == true
41+
//
42+
// T(X::execute(p)) - constructs a T object from p, or throws a
43+
// TypeError exception if p doesn't have an appropriate type.
44+
//
45+
// X::check(p), convertible to bool. True iff T(X::execute(p)) will
46+
// not throw.
47+
template <class T>
48+
struct extract_object_manager
49+
{
50+
BOOST_STATIC_CONSTANT(bool, is_specialized = false);
51+
};
52+
53+
// A metafunction returning true iff its argument is an object manager.
2354
template <class T>
2455
struct is_object_manager
2556
{
2657
private:
58+
// handle the cases that would otherwise require partial specialization
2759
BOOST_STATIC_CONSTANT(bool, hdl = is_handle<T>::value);
2860
BOOST_STATIC_CONSTANT(bool, borrowed = python::detail::is_borrowed_ptr<T>::value);
61+
BOOST_STATIC_CONSTANT(bool, extract_specialized = extract_object_manager<T>::is_specialized);
2962
public:
30-
BOOST_STATIC_CONSTANT(bool, value = (hdl | borrowed));
63+
BOOST_STATIC_CONSTANT(bool, value = (hdl | borrowed | extract_specialized));
3164
};
3265

3366
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 PYTYPE_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
7+
# define PYTYPE_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
8+
9+
# include <boost/python/converter/pytype_result_from_python.hpp>
10+
# include <boost/python/detail/raw_pyobject.hpp>
11+
# include <boost/python/cast.hpp>
12+
# include <boost/python/detail/wrap_python.hpp>
13+
14+
namespace boost { namespace python { namespace converter {
15+
16+
// Provide a forward declaration as a convenience for clients, who all
17+
// need it.
18+
template <class T> struct extract_object_manager;
19+
20+
// Derive specializations of extract_object_manager from this class
21+
// when T is an object manager for a particular Python type hierarchy.
22+
//
23+
template <PyTypeObject* pytype, class T>
24+
struct pytype_extract_object_manager
25+
{
26+
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
27+
static inline python::detail::new_reference execute(PyObject*);
28+
static inline bool check(PyObject* x);
29+
};
30+
31+
//
32+
// implementations
33+
//
34+
template <PyTypeObject* pytype, class T>
35+
inline python::detail::new_reference pytype_extract_object_manager<pytype,T>::execute(PyObject* x)
36+
{
37+
return pytype_result_from_python(pytype, x);
38+
}
39+
40+
template <PyTypeObject* pytype, class T>
41+
inline bool pytype_extract_object_manager<pytype,T>::check(PyObject* x)
42+
{
43+
return ::PyObject_IsInstance(x, python::upcast<PyObject>(pytype));
44+
}
45+
46+
}}} // namespace boost::python::converter
47+
48+
#endif // PYTYPE_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP

include/boost/python/converter/return_from_python.hpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef RETURN_FROM_PYTHON_DWA200265_HPP
77
# define RETURN_FROM_PYTHON_DWA200265_HPP
88

9+
# include <boost/python/converter/object_manager.hpp>
910
# include <boost/python/converter/from_python.hpp>
1011
# include <boost/python/converter/rvalue_from_python_data.hpp>
1112
# include <boost/python/converter/registered.hpp>
@@ -42,24 +43,38 @@ namespace detail
4243
rvalue_from_python_data<T> m_data;
4344
};
4445

46+
template <class T>
47+
struct return_object_manager_from_python
48+
{
49+
typedef T result_type;
50+
result_type operator()(PyObject*) const;
51+
};
52+
4553
template <class T>
4654
struct select_return_from_python
4755
{
56+
BOOST_STATIC_CONSTANT(
57+
bool, obj_mgr = is_object_manager<T>::value);
58+
4859
BOOST_STATIC_CONSTANT(
4960
bool, ptr = is_pointer<T>::value);
5061

5162
BOOST_STATIC_CONSTANT(
5263
bool, ref = is_reference<T>::value);
5364

5465
typedef typename mpl::select_type<
55-
ptr
56-
, return_pointer_from_python<T>
66+
obj_mgr
67+
, return_object_manager_from_python<T>
5768
, typename mpl::select_type<
58-
ref
59-
, return_reference_from_python<T>
60-
, return_rvalue_from_python<T>
69+
ptr
70+
, return_pointer_from_python<T>
71+
, typename mpl::select_type<
72+
ref
73+
, return_reference_from_python<T>
74+
, return_rvalue_from_python<T>
75+
>::type
6176
>::type
62-
>::type type;
77+
>::type type;
6378
};
6479
}
6580

@@ -120,6 +135,14 @@ namespace detail
120135
(pointer_result_from_python)(obj, registered_pointee<T>::converters)
121136
);
122137
}
138+
139+
template <class T>
140+
inline T return_object_manager_from_python<T>::operator()(PyObject* obj) const
141+
{
142+
return T(
143+
extract_object_manager<T>::execute(obj)
144+
);
145+
}
123146
}
124147

125148
}}} // namespace boost::python::converter

0 commit comments

Comments
 (0)