Skip to content

Commit 71032f6

Browse files
committed
New conversion mechanism, builtin converters
[SVN r12590]
1 parent 088b1ca commit 71032f6

27 files changed

Lines changed: 1345 additions & 714 deletions

Jamfile

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,47 @@ PYTHON_PROPERTIES
88
+= <metrowerks><*><cxxflags>"-inline deferred"
99
<cxx><*><include>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers
1010
<define>BOOST_PYTHON_DYNAMIC_LIB
11-
<define>BOOST_PYTHON_V2
12-
;
13-
14-
15-
dll bpl
16-
:
17-
src/converter/body.cpp
18-
src/converter/handle.cpp
19-
src/converter/registry.cpp
20-
src/converter/wrapper.cpp
21-
src/converter/unwrap.cpp
22-
src/converter/unwrapper.cpp
23-
src/converter/type_id.cpp
24-
src/object/class.cpp
25-
src/object/function.cpp
26-
src/object/inheritance.cpp
27-
src/errors.cpp
28-
src/module.cpp
29-
src/objects.cpp
30-
:
31-
$(PYTHON_PROPERTIES)
32-
<define>BOOST_PYTHON_SOURCE
33-
;
34-
35-
extension m1 : test/m1.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
36-
:
37-
: debug-python ;
38-
39-
extension m2 : test/m2.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
11+
<define>BOOST_PYTHON_V2
12+
;
13+
14+
{
15+
dll bpl
16+
:
17+
src/converter/from_python.cpp
18+
src/converter/to_python.cpp
19+
src/converter/registry.cpp
20+
src/converter/type_id.cpp
21+
src/object/class.cpp
22+
src/object/function.cpp
23+
src/object/inheritance.cpp
24+
src/errors.cpp
25+
src/module.cpp
26+
src/objects.cpp
27+
src/converter/builtin_converters.cpp
28+
:
29+
$(PYTHON_PROPERTIES)
30+
<define>BOOST_PYTHON_SOURCE
31+
;
32+
33+
extension m1 : test/m1.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
34+
:
35+
: debug-python
36+
;
37+
38+
extension m2 : test/m2.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
4039
:
4140
: debug-python ;
4241

43-
boost-python-runtest try : test/newtest.py <lib>m1 <lib>m2 : : debug-python ;
42+
boost-python-runtest try : test/newtest.py <lib>m1 <lib>m2 : : debug-python ;
43+
44+
extension builtin_converters_ext : test/test_builtin_converters.cpp <lib>bpl
45+
:
46+
: debug-python
47+
;
48+
49+
boost-python-runtest test_builtin_converters : test/test_builtin_converters.py
50+
<lib>builtin_converters_ext
51+
:
52+
: debug-python
53+
;
54+
}

include/boost/python/converter/class.hpp

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,67 @@
77
# define CLASS_DWA20011215_HPP
88

99
# include <boost/python/object/class.hpp>
10-
# include <boost/python/converter/unwrapper.hpp>
10+
# include <boost/python/converter/from_python.hpp>
1111

1212
namespace boost { namespace python { namespace converter {
1313

1414
template <class T>
15-
struct class_unwrapper
16-
: private unwrapper<T&>
17-
, private unwrapper<T const&>
18-
, private unwrapper<T*>
19-
, private unwrapper<T const*>
15+
struct class_from_python_converter
2016
{
21-
protected:
22-
# ifdef __GNUC__ // suppress warning that "all member functions are private" (duh)
23-
void uncallable();
24-
# endif
25-
private:
26-
void* can_convert(PyObject*) const;
27-
T& convert(PyObject*, void*, boost::type<T&>) const;
28-
T const& convert(PyObject*, void*, boost::type<T const&>) const;
29-
T* convert(PyObject*, void*, boost::type<T*>) const;
30-
T const* convert(PyObject*, void*, boost::type<T const*>) const;
17+
class_from_python_converter();
18+
19+
static void* convertible(PyObject*);
20+
static T& convert_ref(PyObject*, from_python_data&);
21+
static T const& convert_cref(PyObject*, from_python_data&);
22+
static T* convert_ptr(PyObject*, from_python_data&);
23+
static T const* convert_cptr(PyObject*, from_python_data&);
24+
25+
from_python_converter<T&> to_ref;
26+
from_python_converter<T const&> to_cref;
27+
from_python_converter<T*> to_ptr;
28+
from_python_converter<T const*> to_cptr;
3129
};
3230

3331
//
3432
// implementations
3533
//
3634
template <class T>
37-
void* class_unwrapper<T>::can_convert(PyObject* p) const
35+
class_from_python_converter<T>::class_from_python_converter()
36+
: to_ref(convertible, convert_ref)
37+
, to_cref(convertible, convert_cref)
38+
, to_ptr(convertible, convert_ptr)
39+
, to_cptr(convertible, convert_cptr)
40+
{}
41+
42+
template <class T>
43+
T& class_from_python_converter<T>::convert_ref(PyObject*, from_python_data& x)
3844
{
39-
return objects::find_instance<T>(p);
45+
return *static_cast<T*>(x.stage1);
4046
}
4147

4248
template <class T>
43-
T& class_unwrapper<T>::convert(PyObject*, void* found, boost::type<T&>) const
49+
T const& class_from_python_converter<T>::convert_cref(PyObject*, from_python_data& x)
4450
{
45-
return *static_cast<T*>(found);
51+
return *static_cast<T*>(x.stage1);
4652
}
53+
4754

4855
template <class T>
49-
T const& class_unwrapper<T>::convert(PyObject*, void* found, boost::type<T const&>) const
56+
T* class_from_python_converter<T>::convert_ptr(PyObject*, from_python_data& x)
5057
{
51-
return *static_cast<T*>(found);
58+
return static_cast<T*>(x.stage1);
5259
}
5360

5461
template <class T>
55-
T* class_unwrapper<T>::convert(PyObject*, void* found, boost::type<T*>) const
62+
T const* class_from_python_converter<T>::convert_cptr(PyObject*, from_python_data& x)
5663
{
57-
return static_cast<T*>(found);
64+
return static_cast<T*>(x.stage1);
5865
}
5966

6067
template <class T>
61-
T const* class_unwrapper<T>::convert(PyObject*, void* found, boost::type<T const*>) const
68+
void* class_from_python_converter<T>::convertible(PyObject* p)
6269
{
63-
return static_cast<T*>(found);
70+
return objects::find_instance<T>(p);
6471
}
6572

6673
}}} // namespace boost::python::converter

include/boost/python/converter/registration.hpp

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@
99
# include <boost/python/converter/registry.hpp>
1010
# include <boost/python/detail/wrap_python.hpp>
1111
# include <boost/python/detail/config.hpp>
12+
# include <boost/mpl/pop_front.hpp>
13+
# include <boost/mpl/for_each.hpp>
14+
# include <boost/mpl/front.hpp>
1215
# include <utility>
1316
# ifdef BOOST_PYTHON_TRACE
1417
# include <iostream>
1518
# endif
1619

1720
namespace boost { namespace python { namespace converter {
1821

19-
struct BOOST_PYTHON_DECL wrapper_base;
20-
struct BOOST_PYTHON_DECL unwrapper_base;
22+
template <class T> struct from_python_converter;
23+
template <class T> struct target;
24+
template <class T> struct source;
2125

2226
// This class is really sort of a "templated namespace". It manages a
2327
// static data member which refers to the registry entry for T. This
@@ -28,55 +32,115 @@ struct registration
2832
{
2933
public: // member functions
3034
// Return a converter which can convert the given Python object to
31-
// T, or 0 if no such converter exists
32-
static std::pair<unwrapper_base*,void*> unwrapper(PyObject*);
35+
// T, or 0 if no such converter exists. Fill in data with
36+
// the result of the converter's check function
37+
static from_python_converter<T> const* get_from_python(PyObject*, void*& data);
3338

3439
// Return a converter which can convert T to a Python object, or 0
3540
// if no such converter exists
36-
static wrapper_base* wrapper();
41+
static to_python_function<T>::type get_to_python();
3742

43+
static registry::entry* find_entry();
3844
private: // helper functions
3945
static registry::entry* entry();
40-
static registry::entry* find_entry();
46+
static registry::entry* known_entry();
4147

4248
private: // data members
4349
static registry::entry* m_registry_entry;
4450
};
4551

52+
namespace detail
53+
{
54+
// An MPL BinaryMetaFunction class which initializes the
55+
// registration entry for the target type of its 2nd argument.
56+
struct setup_target_registration
57+
{
58+
template <class Ignored, class T> struct apply
59+
{
60+
typedef T type;
61+
static void execute()
62+
{
63+
typedef typename target<T>::type target_t;
64+
registration<target_t>::find_entry();
65+
}
66+
};
67+
};
68+
69+
template <class T>
70+
struct find_return_value_entry
71+
{
72+
static void execute() { registration<T>::find_entry(); }
73+
};
74+
75+
template <>
76+
struct find_return_value_entry<void>
77+
{
78+
static void execute() {}
79+
};
80+
81+
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
82+
template <>
83+
struct find_return_value_entry<void const>
84+
{
85+
static void execute() {}
86+
};
87+
# endif
88+
}
89+
90+
template <class Sequence>
91+
void acquire_registrations(Sequence signature)
92+
{
93+
typedef typename mpl::pop_front<Sequence>::sequence args;
94+
typedef typename mpl::front<Sequence>::type return_type;
95+
96+
mpl::for_each<args, void, detail::setup_target_registration>::execute();
97+
98+
typedef typename source<return_type>::type return_source_type;
99+
detail::find_return_value_entry<return_source_type>::execute();
100+
}
101+
102+
46103
// because this is static POD data it will be initialized to zero
47104
template <class T>
48105
registry::entry* registration<T>::m_registry_entry;
49106

50107
template <class T>
51108
registry::entry* registration<T>::find_entry()
52109
{
53-
return registry::find(type_id<T>());
110+
return m_registry_entry = registry::find(type_id<T>());
54111
}
55112

56113
template <class T>
57114
inline registry::entry* registration<T>::entry()
58115
{
59116
if (!m_registry_entry)
60-
m_registry_entry = find_entry();
117+
find_entry();
61118
return m_registry_entry;
62119
}
63120

64121
template <class T>
65-
std::pair<unwrapper_base*,void*> registration<T>::unwrapper(PyObject* p)
122+
inline registry::entry* registration<T>::known_entry()
66123
{
67-
# ifdef BOOST_PYTHON_TRACE
68-
std::cout << "retrieving unwrapper for " << type_id<T>() << std::endl;
69-
# endif
70-
return entry()->unwrapper(p);
124+
assert(m_registry_entry != 0);
125+
return m_registry_entry;
126+
}
127+
128+
template <class T>
129+
from_python_converter<T> const* registration<T>::get_from_python(PyObject* p, void*& data)
130+
{
131+
return static_cast<from_python_converter<T> const*>(
132+
known_entry()->get_from_python(p, data)
133+
);
71134
}
72135

73136
template <class T>
74-
wrapper_base* registration<T>::wrapper()
137+
typename to_python_function<T>::type registration<T>::get_to_python()
75138
{
76139
# ifdef BOOST_PYTHON_TRACE
77140
std::cout << "retrieving wrapper for " << type_id<T>() << std::endl;
78141
# endif
79-
return entry()->wrapper();
142+
return reinterpret_cast<to_python_function<T>::type>(
143+
known_entry()->get_to_python());
80144
}
81145

82146
}}} // namespace boost::python::converter

0 commit comments

Comments
 (0)