2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 06:02:14 +00:00

Major simplification of from_python conversion avoids registering

converters for every class.


[SVN r16669]
This commit is contained in:
Dave Abrahams
2002-12-20 00:04:40 +00:00
parent b8edd99dbd
commit 3d874d1618
12 changed files with 177 additions and 151 deletions

View File

@@ -7,11 +7,15 @@
#include <boost/python/converter/from_python.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/converter/rvalue_from_python_data.hpp>
#include <boost/python/object/find_instance.hpp>
#include <boost/python/handle.hpp>
#include <boost/python/detail/raw_pyobject.hpp>
#include <boost/python/cast.hpp>
#include <boost/lexical_cast.hpp>
#include <vector>
#include <algorithm>
@@ -38,18 +42,28 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
PyObject* source
, registration const& converters)
{
rvalue_from_python_chain const* chain = converters.rvalue_chain;
rvalue_from_python_stage1_data data;
data.convertible = 0;
for (;chain != 0; chain = chain->next)
// First check to see if it's embedded in an extension class
// instance, as a special case.
data.convertible = objects::find_instance_impl(source, converters.target_type);
if (data.convertible)
{
void* r = chain->convertible(source);
if (r != 0)
data.construct = 0;
}
else
{
for (rvalue_from_python_chain const* chain = converters.rvalue_chain;
chain != 0;
chain = chain->next)
{
data.convertible = r;
data.construct = chain->construct;
break;
void* r = chain->convertible(source);
if (r != 0)
{
data.convertible = r;
data.construct = chain->construct;
break;
}
}
}
return data;
@@ -111,8 +125,12 @@ BOOST_PYTHON_DECL void* get_lvalue_from_python(
PyObject* source
, registration const& converters)
{
// Check to see if it's embedded in a class instance
void* x = objects::find_instance_impl(source, converters.target_type);
if (x)
return x;
lvalue_from_python_chain const* chain = converters.lvalue_chain;
for (;chain != 0; chain = chain->next)
{
void* r = chain->convert(source);
@@ -138,38 +156,45 @@ namespace
return true;
}
void unvisit(rvalue_from_python_chain const* chain)
// RAII class for managing global visited marks.
struct unvisit
{
visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain);
assert(p != visited.end());
visited.erase(p);
}
unvisit(rvalue_from_python_chain const* chain)
: chain(chain) {}
~unvisit()
{
visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain);
assert(p != visited.end());
visited.erase(p);
}
private:
rvalue_from_python_chain const* chain;
};
}
BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain(
BOOST_PYTHON_DECL bool implicit_rvalue_convertible_from_python(
PyObject* source
, registration const& converters)
{
if (objects::find_instance_impl(source, converters.target_type))
return true;
rvalue_from_python_chain const* chain = converters.rvalue_chain;
if (!visit(chain))
return 0;
return false;
unvisit protect(chain);
try
for (;chain != 0; chain = chain->next)
{
for (;chain != 0; chain = chain->next)
{
if (chain->convertible(source))
break;
}
if (chain->convertible(source))
return true;
}
catch(...)
{
unvisit(chain);
throw;
}
unvisit(chain);
return chain;
return false;
}
namespace