Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/python/src/converter/registry.cpp @ 45

Last change on this file since 45 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 7.1 KB
Line 
1//  Copyright David Abrahams 2001.
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#include <boost/python/converter/registry.hpp>
6#include <boost/python/converter/registrations.hpp>
7#include <boost/python/converter/builtin_converters.hpp>
8
9#include <set>
10#include <stdexcept>
11
12#if defined(__APPLE__) && defined(__MACH__) && defined(__GNUC__) \
13 && __GNUC__ == 3 && __GNUC_MINOR__ <= 4 && !defined(__APPLE_CC__)
14# define BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
15#endif
16
17#if defined(BOOST_PYTHON_TRACE_REGISTRY) \
18 || defined(BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND)
19# include <iostream>
20#endif
21
22namespace boost { namespace python { namespace converter { 
23
24BOOST_PYTHON_DECL PyTypeObject* registration::get_class_object() const
25{
26    if (this->m_class_object == 0)
27    {
28        ::PyErr_Format(
29            PyExc_TypeError
30            , const_cast<char*>("No Python class registered for C++ class %s")
31            , this->target_type.name());
32   
33        throw_error_already_set();
34    }
35   
36    return this->m_class_object;
37}
38 
39BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source) const
40{
41    if (this->m_to_python == 0)
42    {
43        handle<> msg(
44            ::PyString_FromFormat(
45                "No to_python (by-value) converter found for C++ type: %s"
46                , this->target_type.name()
47                )
48            );
49           
50        PyErr_SetObject(PyExc_TypeError, msg.get());
51
52        throw_error_already_set();
53    }
54       
55    return source == 0
56        ? incref(Py_None)
57        : this->m_to_python(const_cast<void*>(source));
58}
59
60namespace // <unnamed>
61{
62  typedef registration entry;
63 
64  typedef std::set<entry> registry_t;
65 
66#ifndef BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
67  registry_t& entries()
68  {
69      static registry_t registry;
70
71# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
72      static bool builtin_converters_initialized = false;
73      if (!builtin_converters_initialized)
74      {
75          // Make this true early because registering the builtin
76          // converters will cause recursion.
77          builtin_converters_initialized = true;
78         
79          initialize_builtin_converters();
80      }
81#  ifdef BOOST_PYTHON_TRACE_REGISTRY
82      std::cout << "registry: ";
83      for (registry_t::iterator p = registry.begin(); p != registry.end(); ++p)
84      {
85          std::cout << p->target_type << "; ";
86      }
87      std::cout << '\n';
88#  endif
89# endif
90      return registry;
91  }
92#else
93  registry_t& static_registry()
94  {
95    static registry_t result;
96    return result;
97  }
98
99  bool static_builtin_converters_initialized()
100  {
101    static bool result = false;
102    if (result == false) {
103      result = true;
104      std::cout << std::flush;
105      return false;
106    }
107    return true;
108  }
109
110  registry_t& entries()
111  {
112# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
113      if (!static_builtin_converters_initialized())
114      {
115          initialize_builtin_converters();
116      }
117#  ifdef BOOST_PYTHON_TRACE_REGISTRY
118      std::cout << "registry: ";
119      for (registry_t::iterator p = static_registry().begin(); p != static_registry().end(); ++p)
120      {
121          std::cout << p->target_type << "; ";
122      }
123      std::cout << '\n';
124#  endif
125# endif
126      return static_registry();
127  }
128#endif // BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
129
130  entry* get(type_info type, bool is_shared_ptr = false)
131  {
132#  ifdef BOOST_PYTHON_TRACE_REGISTRY
133      registry_t::iterator p = entries().find(entry(type));
134     
135      std::cout << "looking up " << type << ": "
136                << (p == entries().end() || p->target_type != type
137                    ? "...NOT found\n" : "...found\n");
138#  endif
139      std::pair<registry_t::const_iterator,bool> pos_ins
140          = entries().insert(entry(type,is_shared_ptr));
141     
142#  if __MWERKS__ >= 0x3000
143      // do a little invariant checking if a change was made
144      if ( pos_ins.second )
145          assert(entries().invariants());
146#  endif
147      return const_cast<entry*>(&*pos_ins.first);
148  }
149} // namespace <unnamed>
150
151namespace registry
152{
153  void insert(to_python_function_t f, type_info source_t)
154  {
155#  ifdef BOOST_PYTHON_TRACE_REGISTRY
156      std::cout << "inserting to_python " << source_t << "\n";
157#  endif
158      to_python_function_t& slot = get(source_t)->m_to_python;
159     
160      assert(slot == 0); // we have a problem otherwise
161      if (slot != 0)
162      {
163          std::string msg = (
164              std::string("to-Python converter for ")
165              + source_t.name()
166              + " already registered; second conversion method ignored."
167          );
168         
169          if ( ::PyErr_Warn( NULL, const_cast<char*>(msg.c_str()) ) )
170          {
171              throw_error_already_set();
172          }
173      }
174      slot = f;
175  }
176
177  // Insert an lvalue from_python converter
178  void insert(convertible_function convert, type_info key)
179  {
180#  ifdef BOOST_PYTHON_TRACE_REGISTRY
181      std::cout << "inserting lvalue from_python " << key << "\n";
182#  endif
183      entry* found = get(key);
184      lvalue_from_python_chain *registration = new lvalue_from_python_chain;
185      registration->convert = convert;
186      registration->next = found->lvalue_chain;
187      found->lvalue_chain = registration;
188     
189      insert(convert, 0, key);
190  }
191
192  // Insert an rvalue from_python converter
193  void insert(void* (*convertible)(PyObject*)
194              , constructor_function construct
195              , type_info key)
196  {
197#  ifdef BOOST_PYTHON_TRACE_REGISTRY
198      std::cout << "inserting rvalue from_python " << key << "\n";
199#  endif
200      entry* found = get(key);
201      rvalue_from_python_chain *registration = new rvalue_from_python_chain;
202      registration->convertible = convertible;
203      registration->construct = construct;
204      registration->next = found->rvalue_chain;
205      found->rvalue_chain = registration;
206  }
207
208  // Insert an rvalue from_python converter
209  void push_back(void* (*convertible)(PyObject*)
210              , constructor_function construct
211              , type_info key)
212  {
213#  ifdef BOOST_PYTHON_TRACE_REGISTRY
214      std::cout << "push_back rvalue from_python " << key << "\n";
215#  endif
216      rvalue_from_python_chain** found = &get(key)->rvalue_chain;
217      while (*found != 0)
218          found = &(*found)->next;
219     
220      rvalue_from_python_chain *registration = new rvalue_from_python_chain;
221      registration->convertible = convertible;
222      registration->construct = construct;
223      registration->next = 0;
224      *found = registration;
225  }
226
227  registration const& lookup(type_info key)
228  {
229      return *get(key);
230  }
231
232  registration const& lookup_shared_ptr(type_info key)
233  {
234      return *get(key, true);
235  }
236
237  registration const* query(type_info type)
238  {
239      registry_t::iterator p = entries().find(entry(type));
240#  ifdef BOOST_PYTHON_TRACE_REGISTRY
241      std::cout << "querying " << type
242                << (p == entries().end() || p->target_type != type
243                    ? "...NOT found\n" : "...found\n");
244#  endif
245      return (p == entries().end() || p->target_type != type) ? 0 : &*p;
246  }
247} // namespace registry
248
249}}} // namespace boost::python::converter
Note: See TracBrowser for help on using the repository browser.