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
1720namespace 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
47104template <class T >
48105registry::entry* registration<T>::m_registry_entry;
49106
50107template <class T >
51108registry::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
56113template <class T >
57114inline 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
64121template <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
73136template <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