registry.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 302 行

CPP
302
字号
//  Copyright David Abrahams 2001.// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)#include <boost/python/converter/registry.hpp>#include <boost/python/converter/registrations.hpp>#include <boost/python/converter/builtin_converters.hpp>#include <set>#include <stdexcept>#if defined(__APPLE__) && defined(__MACH__) && defined(__GNUC__) \ && __GNUC__ == 3 && __GNUC_MINOR__ <= 4 && !defined(__APPLE_CC__)# define BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND#endif#if defined(BOOST_PYTHON_TRACE_REGISTRY) \ || defined(BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND)# include <iostream>#endifnamespace boost { namespace python { namespace converter { BOOST_PYTHON_DECL PyTypeObject const* registration::expected_from_python_type() const{    if (this->m_class_object != 0)        return this->m_class_object;    std::set<PyTypeObject const*> pool;    for(rvalue_from_python_chain* r = rvalue_chain; r ; r=r->next)        if(r->expected_pytype)            pool.insert(r->expected_pytype());    //for now I skip the search for common base    if (pool.size()==1)        return *pool.begin();    return 0;}BOOST_PYTHON_DECL PyTypeObject const* registration::to_python_target_type() const{    if (this->m_class_object != 0)        return this->m_class_object;    if (this->m_to_python_target_type != 0)        return this->m_to_python_target_type();    return 0;}BOOST_PYTHON_DECL PyTypeObject* registration::get_class_object() const{    if (this->m_class_object == 0)    {        ::PyErr_Format(            PyExc_TypeError            , const_cast<char*>("No Python class registered for C++ class %s")            , this->target_type.name());            throw_error_already_set();    }        return this->m_class_object;}  BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source) const{    if (this->m_to_python == 0)    {        handle<> msg(            ::PyString_FromFormat(                "No to_python (by-value) converter found for C++ type: %s"                , this->target_type.name()                )            );                    PyErr_SetObject(PyExc_TypeError, msg.get());        throw_error_already_set();    }            return source == 0        ? incref(Py_None)        : this->m_to_python(const_cast<void*>(source));}namespace{  template< typename T >  void delete_node( T* node )  {      if( !!node && !!node->next )          delete_node( node->next );      delete node;  }}registration::~registration(){  delete_node(lvalue_chain);  delete_node(rvalue_chain);}namespace // <unnamed>{  typedef registration entry;    typedef std::set<entry> registry_t;  #ifndef BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND  registry_t& entries()  {      static registry_t registry;# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION      static bool builtin_converters_initialized = false;      if (!builtin_converters_initialized)      {          // Make this true early because registering the builtin          // converters will cause recursion.          builtin_converters_initialized = true;                    initialize_builtin_converters();      }#  ifdef BOOST_PYTHON_TRACE_REGISTRY      std::cout << "registry: ";      for (registry_t::iterator p = registry.begin(); p != registry.end(); ++p)      {          std::cout << p->target_type << "; ";      }      std::cout << '\n';#  endif # endif       return registry;  }#else  registry_t& static_registry()  {    static registry_t result;    return result;  }  bool static_builtin_converters_initialized()  {    static bool result = false;    if (result == false) {      result = true;      std::cout << std::flush;      return false;    }    return true;  }  registry_t& entries()  {# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION      if (!static_builtin_converters_initialized())      {          initialize_builtin_converters();      }#  ifdef BOOST_PYTHON_TRACE_REGISTRY      std::cout << "registry: ";      for (registry_t::iterator p = static_registry().begin(); p != static_registry().end(); ++p)      {          std::cout << p->target_type << "; ";      }      std::cout << '\n';#  endif # endif       return static_registry();  }#endif // BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND  entry* get(type_info type, bool is_shared_ptr = false)  {#  ifdef BOOST_PYTHON_TRACE_REGISTRY      registry_t::iterator p = entries().find(entry(type));            std::cout << "looking up " << type << ": "                << (p == entries().end() || p->target_type != type                    ? "...NOT found\n" : "...found\n");#  endif      std::pair<registry_t::const_iterator,bool> pos_ins          = entries().insert(entry(type,is_shared_ptr));      #  if __MWERKS__ >= 0x3000      // do a little invariant checking if a change was made      if ( pos_ins.second )          assert(entries().invariants());#  endif      return const_cast<entry*>(&*pos_ins.first);  }} // namespace <unnamed>namespace registry{  void insert(to_python_function_t f, type_info source_t, PyTypeObject const* (*to_python_target_type)())  {#  ifdef BOOST_PYTHON_TRACE_REGISTRY      std::cout << "inserting to_python " << source_t << "\n";#  endif       entry* slot = get(source_t);            assert(slot->m_to_python == 0); // we have a problem otherwise      if (slot->m_to_python != 0)      {          std::string msg = (              std::string("to-Python converter for ")              + source_t.name()              + " already registered; second conversion method ignored."          );                    if ( ::PyErr_Warn( NULL, const_cast<char*>(msg.c_str()) ) )          {              throw_error_already_set();          }      }      slot->m_to_python = f;      slot->m_to_python_target_type = to_python_target_type;  }  // Insert an lvalue from_python converter  void insert(convertible_function convert, type_info key, PyTypeObject const* (*exp_pytype)())  {#  ifdef BOOST_PYTHON_TRACE_REGISTRY      std::cout << "inserting lvalue from_python " << key << "\n";#  endif       entry* found = get(key);      lvalue_from_python_chain *registration = new lvalue_from_python_chain;      registration->convert = convert;      registration->next = found->lvalue_chain;      found->lvalue_chain = registration;            insert(convert, 0, key,exp_pytype);  }  // Insert an rvalue from_python converter  void insert(void* (*convertible)(PyObject*)              , constructor_function construct              , type_info key              , PyTypeObject const* (*exp_pytype)())  {#  ifdef BOOST_PYTHON_TRACE_REGISTRY      std::cout << "inserting rvalue from_python " << key << "\n";#  endif       entry* found = get(key);      rvalue_from_python_chain *registration = new rvalue_from_python_chain;      registration->convertible = convertible;      registration->construct = construct;      registration->expected_pytype = exp_pytype;      registration->next = found->rvalue_chain;      found->rvalue_chain = registration;  }  // Insert an rvalue from_python converter  void push_back(void* (*convertible)(PyObject*)              , constructor_function construct              , type_info key              , PyTypeObject const* (*exp_pytype)())  {#  ifdef BOOST_PYTHON_TRACE_REGISTRY      std::cout << "push_back rvalue from_python " << key << "\n";#  endif       rvalue_from_python_chain** found = &get(key)->rvalue_chain;      while (*found != 0)          found = &(*found)->next;            rvalue_from_python_chain *registration = new rvalue_from_python_chain;      registration->convertible = convertible;      registration->construct = construct;      registration->expected_pytype = exp_pytype;      registration->next = 0;      *found = registration;  }  registration const& lookup(type_info key)  {      return *get(key);  }  registration const& lookup_shared_ptr(type_info key)  {      return *get(key, true);  }  registration const* query(type_info type)  {      registry_t::iterator p = entries().find(entry(type));#  ifdef BOOST_PYTHON_TRACE_REGISTRY      std::cout << "querying " << type                << (p == entries().end() || p->target_type != type                    ? "...NOT found\n" : "...found\n");#  endif       return (p == entries().end() || p->target_type != type) ? 0 : &*p;  }} // namespace registry}}} // namespace boost::python::converter

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?