mirror of
https://github.com/boostorg/python.git
synced 2026-01-27 07:02:15 +00:00
Major simplification of from_python conversion avoids registering
converters for every class. [SVN r16669]
This commit is contained in:
@@ -77,21 +77,21 @@ namespace detail
|
||||
template <detail::operator_id, class L, class R>
|
||||
struct operator_;
|
||||
|
||||
// Register a to_python converter for a class T, depending on the
|
||||
// type of the first (tag) argument. The 2nd argument is a pointer
|
||||
// to the type of holder that must be created. The 3rd argument is a
|
||||
// Register to_python converters for a class T. The first argument
|
||||
// will be mpl::true_c unless noncopyable was specified as a
|
||||
// class_<...> template parameter. The 2nd argument is a pointer to
|
||||
// the type of holder that must be created. The 3rd argument is a
|
||||
// reference to the Python type object to be created.
|
||||
template <class T, class SelectHolder>
|
||||
static inline void register_copy_constructor(mpl::bool_c<true> const&, SelectHolder const& , T* = 0)
|
||||
inline void register_class_to_python(mpl::true_c copyable, SelectHolder selector, T* = 0)
|
||||
{
|
||||
typedef typename SelectHolder::type holder;
|
||||
force_instantiate(objects::class_cref_wrapper<T, objects::make_instance<T,holder> >());
|
||||
SelectHolder::register_();
|
||||
}
|
||||
|
||||
// Tag dispatched to have no effect.
|
||||
template <class T, class SelectHolder>
|
||||
static inline void register_copy_constructor(mpl::bool_c<false> const&, SelectHolder const&, T* = 0)
|
||||
inline void register_class_to_python(mpl::false_c copyable, SelectHolder selector, T* = 0)
|
||||
{
|
||||
SelectHolder::register_();
|
||||
}
|
||||
@@ -125,20 +125,14 @@ namespace detail
|
||||
|
||||
template <class T, class Fn>
|
||||
struct virtual_function_default
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
: assertion<is_polymorphic<T> >::failed
|
||||
, assertion<is_member_function_pointer<Fn> >::failed
|
||||
# endif
|
||||
{
|
||||
template <class Default>
|
||||
static void
|
||||
must_be_derived_class_member(Default const&)
|
||||
{
|
||||
typedef typename assertion<mpl::logical_not<is_same<Default,Fn> > >::failed test0;
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename assertion<is_polymorphic<T> >::failed test1;
|
||||
typedef typename assertion<is_member_function_pointer<Fn> >::failed test2;
|
||||
# endif
|
||||
not_a_derived_class_member<Default>(Fn());
|
||||
}
|
||||
};
|
||||
@@ -473,7 +467,7 @@ inline void class_<T,X1,X2,X3>::register_() const
|
||||
{
|
||||
objects::register_class_from_python<T,bases>();
|
||||
|
||||
detail::register_copy_constructor<T>(
|
||||
detail::register_class_to_python<T>(
|
||||
mpl::bool_c<is_copyable>()
|
||||
, holder_selector::execute((held_type*)0)
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ struct rvalue_from_python_chain;
|
||||
BOOST_PYTHON_DECL void* get_lvalue_from_python(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain(
|
||||
BOOST_PYTHON_DECL bool implicit_rvalue_convertible_from_python(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef IMPLICIT_DWA2002326_HPP
|
||||
# define IMPLICIT_DWA2002326_HPP
|
||||
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registrations.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
|
||||
# include <boost/python/extract.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class Source, class Target>
|
||||
@@ -16,39 +19,22 @@ struct implicit
|
||||
{
|
||||
static void* convertible(PyObject* obj)
|
||||
{
|
||||
// Find a converter chain which can produce a Source instance
|
||||
// from obj. The user has told us that Source can be converted
|
||||
// to Target, and instantiating construct() below, ensures
|
||||
// that at compile-time.
|
||||
return const_cast<rvalue_from_python_chain*>(
|
||||
converter::implicit_conversion_chain(obj, registered<Source>::converters));
|
||||
// Find a converter which can produce a Source instance from
|
||||
// obj. The user has told us that Source can be converted to
|
||||
// Target, and instantiating construct() below, ensures that
|
||||
// at compile-time.
|
||||
return implicit_rvalue_convertible_from_python(obj, registered<Source>::converters)
|
||||
? obj : 0;
|
||||
}
|
||||
|
||||
static void construct(PyObject* obj, rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
// This is the chain we got from the convertible step
|
||||
rvalue_from_python_chain const* chain
|
||||
= static_cast<rvalue_from_python_chain*>(data->convertible);
|
||||
|
||||
// Call the convertible function again
|
||||
rvalue_from_python_data<Source> intermediate_data(chain->convertible(obj));
|
||||
|
||||
// Use the result to construct the source type if the first
|
||||
// converter was an rvalue converter.
|
||||
if (chain->construct != 0)
|
||||
chain->construct(obj, &intermediate_data.stage1);
|
||||
|
||||
void* storage = ((rvalue_from_python_storage<Target>*)data)->storage.bytes;
|
||||
# if !defined(BOOST_MSVC) || _MSC_FULL_VER != 13012108 // vc7.01 alpha workaround
|
||||
new (storage) Target(*static_cast<Source*>(intermediate_data.stage1.convertible));
|
||||
# else
|
||||
Target x(*static_cast<Source*>(intermediate_data.stage1.convertible));
|
||||
new (storage) Target(x);
|
||||
# endif
|
||||
|
||||
|
||||
new (storage) Target(extract<Source>(obj)());
|
||||
|
||||
// record successful construction
|
||||
data->convertible = storage;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,11 +6,15 @@
|
||||
#ifndef REGISTRATIONS_DWA2002223_HPP
|
||||
# define REGISTRATIONS_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/converter/convertible_function.hpp>
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -54,7 +58,7 @@ struct BOOST_PYTHON_DECL registration
|
||||
// The unique to_python converter for the associated C++ type.
|
||||
to_python_function_t m_to_python;
|
||||
|
||||
# if defined(__MWERKS__) && __MWERKS__ <= 0x3003
|
||||
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
private:
|
||||
void operator=(registration); // This is not defined, and just keeps MWCW happy.
|
||||
# endif
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/shared_ptr_from_python.hpp>
|
||||
|
||||
# include <boost/python/object/find_instance.hpp>
|
||||
# include <boost/python/object/inheritance.hpp>
|
||||
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
@@ -72,8 +71,6 @@ struct register_base_of
|
||||
template <class Derived, class Bases>
|
||||
inline void register_class_from_python(Derived* = 0, Bases* = 0)
|
||||
{
|
||||
// cause the static registration to be instantiated.
|
||||
python::detail::force_instantiate(instance_finder<Derived>::registration);
|
||||
python::detail::force_instantiate(converter::shared_ptr_from_python<Derived>::registration);
|
||||
|
||||
// register all up/downcasts here
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
# define FIND_INSTANCE_DWA2002312_HPP
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -15,26 +14,6 @@ namespace boost { namespace python { namespace objects {
|
||||
// return 0 in case no such type is held.
|
||||
BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, type_info);
|
||||
|
||||
// This produces a function with the right signature for use in from_python conversions
|
||||
template <class T>
|
||||
struct instance_finder
|
||||
{
|
||||
instance_finder()
|
||||
{
|
||||
converter::registry::insert(&execute, python::type_id<T>());
|
||||
}
|
||||
|
||||
static instance_finder const registration;
|
||||
private:
|
||||
static inline void* execute(PyObject* p)
|
||||
{
|
||||
return find_instance_impl(p, python::type_id<T>());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
instance_finder<T> const instance_finder<T>::registration;
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
#endif // FIND_INSTANCE_DWA2002312_HPP
|
||||
|
||||
@@ -11,6 +11,15 @@
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
struct decref_guard
|
||||
{
|
||||
decref_guard(PyObject* o) : obj(o) {}
|
||||
~decref_guard() { Py_XDECREF(obj); }
|
||||
void cancel() { obj = 0; }
|
||||
private:
|
||||
PyObject* obj;
|
||||
};
|
||||
|
||||
template <class T, class Holder>
|
||||
struct make_instance
|
||||
{
|
||||
@@ -28,22 +37,20 @@ struct make_instance
|
||||
|
||||
if (raw_result != 0)
|
||||
{
|
||||
instance_t* result = (instance_t*)raw_result;
|
||||
try
|
||||
{
|
||||
// construct the new C++ object and install the pointer
|
||||
// in the Python object.
|
||||
construct(result, x)->install(raw_result);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Py_DECREF(raw_result); // reclaim the Python object
|
||||
throw;
|
||||
}
|
||||
decref_guard protect(raw_result);
|
||||
|
||||
instance_t* instance = (instance_t*)raw_result;
|
||||
|
||||
// construct the new C++ object and install the pointer
|
||||
// in the Python object.
|
||||
construct(instance, x)->install(raw_result);
|
||||
|
||||
// Note the position of the internally-stored Holder,
|
||||
// for the sake of destruction
|
||||
result->ob_size = offsetof(instance_t, storage);
|
||||
instance->ob_size = offsetof(instance_t, storage);
|
||||
|
||||
// Release ownership of the python object
|
||||
protect.cancel();
|
||||
}
|
||||
return raw_result;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/object/inheritance.hpp>
|
||||
# include <boost/python/object/find_instance.hpp>
|
||||
# include <boost/python/object/forward.hpp>
|
||||
# include <boost/python/pointee.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
# include <boost/python/object/value_holder.hpp>
|
||||
# include <boost/python/object/pointer_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/object/find_instance.hpp>
|
||||
# include <boost/python/object/make_instance.hpp>
|
||||
# include <boost/python/object/instance.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
@@ -27,11 +26,22 @@ namespace boost { namespace python { namespace objects {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// check_default_constructible --
|
||||
//
|
||||
// Used to give a clean error message when the user doesn't specify
|
||||
// any __init__ functions, but when the class being wrapped doesn't
|
||||
// have an appropriate default constructor (or if
|
||||
// has_back_reference<T> is true, a constructor taking PyObject*).
|
||||
|
||||
// A helpful compile-time assertion which gives a reasonable error
|
||||
// message if T can't be default-constructed.
|
||||
template <class T>
|
||||
static int specify_init_arguments_or_no_init_for_class_(T const&);
|
||||
|
||||
|
||||
// U is expected to take an initial hidden PyObject* in its
|
||||
// constructor. Normally this means U is a virtual function
|
||||
// dispatcher subclass for T.
|
||||
template <class T, class U>
|
||||
void check_default_constructible(T*, U*, mpl::bool_c<true>)
|
||||
{
|
||||
@@ -39,7 +49,9 @@ namespace detail
|
||||
sizeof(specify_init_arguments_or_no_init_for_class_<T>(U((::PyObject*)0)))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Handles the "normal" case where T is held directly and
|
||||
// has_back_reference<T> is not specialized.
|
||||
template <class T>
|
||||
void check_default_constructible(T*, T*, mpl::bool_c<false>)
|
||||
{
|
||||
@@ -47,76 +59,76 @@ namespace detail
|
||||
sizeof(specify_init_arguments_or_no_init_for_class_<T>(T()))
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// select_value_holder/select_pointer_holder --
|
||||
//
|
||||
// An instantiation of one of these data-free class templates is
|
||||
// returned by select_holder::execute(), below. Each provides the
|
||||
// following public interface:
|
||||
//
|
||||
// static void assert_default_constructible() -- called when no
|
||||
// init<...> arguments are specified in class_<T, ...>'s
|
||||
// constructor; causes a compile-time error when T has no
|
||||
// corresponding default constructor.
|
||||
//
|
||||
// typedef ... type -- the class derived from instance_holder
|
||||
// which will manage a Held object in Python class instances
|
||||
//
|
||||
// static type* get() { return 0; } -- just a way to access the
|
||||
// computed type at runtime.
|
||||
//
|
||||
// static void register_() -- forces registration of any
|
||||
// to_python converters corresponding to Held.
|
||||
|
||||
template <class T, class Held>
|
||||
struct select_value_holder
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, selector = (!is_same<T,Held>::value) | has_back_reference<T>::value);
|
||||
BOOST_STATIC_CONSTANT(bool, back_ref = (!is_same<T,Held>::value) | has_back_reference<T>::value);
|
||||
|
||||
static void assert_default_constructible()
|
||||
{
|
||||
detail::check_default_constructible((T*)0,(Held*)0,mpl::bool_c<selector>());
|
||||
detail::check_default_constructible((T*)0,(Held*)0,mpl::bool_c<back_ref>());
|
||||
}
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
selector
|
||||
back_ref
|
||||
, value_holder_back_reference<T,Held>
|
||||
, value_holder<T>
|
||||
>::type type;
|
||||
|
||||
static inline void register_()
|
||||
{
|
||||
select_value_holder::register_(mpl::bool_c<selector>());
|
||||
}
|
||||
static inline void register_() {}
|
||||
|
||||
static type* get() { return 0; }
|
||||
|
||||
private:
|
||||
static inline void register_(mpl::bool_c<true>)
|
||||
{
|
||||
python::detail::force_instantiate(instance_finder<Held>::registration);
|
||||
}
|
||||
|
||||
static inline void register_(mpl::bool_c<false>)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T,class Ptr>
|
||||
struct select_pointer_holder
|
||||
{
|
||||
typedef typename python::pointee<Ptr>::type pointee;
|
||||
BOOST_STATIC_CONSTANT(bool, selector = (!is_same<T,pointee>::value) | has_back_reference<T>::value);
|
||||
BOOST_STATIC_CONSTANT(bool, back_ref = (!is_same<T,pointee>::value) | has_back_reference<T>::value);
|
||||
|
||||
static void assert_default_constructible()
|
||||
{
|
||||
detail::check_default_constructible((T*)0,(pointee*)0,mpl::bool_c<selector>());
|
||||
detail::check_default_constructible((T*)0,(pointee*)0,mpl::bool_c<back_ref>());
|
||||
}
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
selector
|
||||
back_ref
|
||||
, pointer_holder_back_reference<Ptr,T>
|
||||
, pointer_holder<Ptr,T>
|
||||
>::type type;
|
||||
|
||||
static inline void register_()
|
||||
{
|
||||
select_pointer_holder::register_(mpl::bool_c<selector>());
|
||||
select_pointer_holder::register_(mpl::bool_c<back_ref>());
|
||||
}
|
||||
|
||||
static type* get() { return 0; }
|
||||
|
||||
private:
|
||||
static inline void register_(mpl::bool_c<true>)
|
||||
static inline void register_(mpl::true_c)
|
||||
{
|
||||
// not implemented at least until we solve the back
|
||||
// reference issue mentioned in pointer_holder.hpp.
|
||||
//
|
||||
// python::detail::force_instantiate(
|
||||
// class_wrapper<Pointer,pointer_holder_back_reference<Pointer,Value> >());
|
||||
|
||||
python::detail::force_instantiate(instance_finder<Ptr>::registration);
|
||||
python::detail::force_instantiate(instance_finder<pointee>::registration);
|
||||
}
|
||||
|
||||
struct construct_from_pointer
|
||||
@@ -127,37 +139,56 @@ namespace detail
|
||||
}
|
||||
};
|
||||
|
||||
static inline void register_(mpl::bool_c<false>)
|
||||
static inline void register_(mpl::false_c)
|
||||
{
|
||||
python::detail::force_instantiate(
|
||||
objects::class_value_wrapper<Ptr, make_instance<T,type> >());
|
||||
|
||||
python::detail::force_instantiate(
|
||||
instance_finder<Ptr>::registration);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// select_holder<T,Held>::execute((Held*)0)
|
||||
//
|
||||
// implements a compile-time returns an instantiation of
|
||||
// detail::select_value_holder or detail::select_pointer_holder, as
|
||||
// appropriate for class_<T,Held>
|
||||
template <class T, class Held>
|
||||
struct select_holder
|
||||
{
|
||||
// Return the additional size to allocate in Python class
|
||||
// instances to hold the C++ instance data.
|
||||
static inline std::size_t additional_size()
|
||||
{
|
||||
return additional_size_helper(execute((Held*)0));
|
||||
}
|
||||
|
||||
|
||||
// These overloads are an elaborate workaround for deficient
|
||||
// compilers:
|
||||
//
|
||||
// They are meant to be called with a null pointer to the class_'s
|
||||
// Held template argument. The selected overload will create an
|
||||
// appropriate instantiation of select_value_holder or
|
||||
// select_pointer_holder, which is itself an empty class that is
|
||||
// ultimately used to create the class_'s instance_holder subclass
|
||||
// object.
|
||||
|
||||
// No Held was specified; T is held directly by-value
|
||||
static inline detail::select_value_holder<T,T>
|
||||
execute(python::detail::not_specified*)
|
||||
{
|
||||
return detail::select_value_holder<T,T>();
|
||||
}
|
||||
|
||||
// A type derived from T was specified; it is assumed to be a
|
||||
// virtual function dispatcher class, and T is held as Held.
|
||||
static inline detail::select_value_holder<T, Held>
|
||||
execute(T*)
|
||||
{
|
||||
return detail::select_value_holder<T, Held>();
|
||||
}
|
||||
|
||||
// Some other type was specified; Held is assumed to be a (smart)
|
||||
// pointer to T or a class derived from T.
|
||||
static inline detail::select_pointer_holder<T,Held>
|
||||
execute(void*)
|
||||
{
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
# define VALUE_HOLDER_DWA20011215_HPP
|
||||
|
||||
# include <boost/python/object/value_holder_fwd.hpp>
|
||||
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/object/inheritance.hpp>
|
||||
# include <boost/python/object/find_instance.hpp>
|
||||
# include <boost/python/object/forward.hpp>
|
||||
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
|
||||
|
||||
@@ -37,7 +37,9 @@ namespace detail
|
||||
template <class T>
|
||||
static result_type execute(T* p)
|
||||
{
|
||||
// can't use auto_ptr with Intel 5 for some reason
|
||||
// can't use auto_ptr with Intel 5 and VC6 Dinkum library
|
||||
// for some reason. We get link errors against the auto_ptr
|
||||
// copy constructor.
|
||||
# if defined(__ICL) && __ICL < 600
|
||||
typedef boost::shared_ptr<T> smart_pointer;
|
||||
# else
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user