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 + -
显示快捷键?