mirror of
https://github.com/boostorg/python.git
synced 2026-01-22 17:32:55 +00:00
Use make_function uniformly to build callable objects.
Fix wstring support so it doesn't break gcc2.95.x, which has no wstring. Modify CallPolicies protocol so it can safely adjust the argument tuple. [SVN r20090]
This commit is contained in:
@@ -112,7 +112,9 @@ BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUn
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),x.size()))
|
||||
# ifndef BOOST_NO_STD_WSTRING
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),x.size()))
|
||||
# endif
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x))
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/return_by_value.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
|
||||
# include <boost/python/converter/builtin_converters.hpp>
|
||||
|
||||
@@ -24,12 +24,14 @@
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/is_member_pointer.hpp>
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
# endif
|
||||
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/vector/vector10.hpp>
|
||||
|
||||
# include <boost/bind.hpp>
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
@@ -43,97 +45,57 @@ namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Raw Getter and Setter function generators. These class templates
|
||||
// generate static functions which can be bound together with
|
||||
// policies and wrapped to generate the python callable objects
|
||||
// mentioned above.
|
||||
//
|
||||
|
||||
//
|
||||
// Generates get and set functions for access through
|
||||
// pointers-to-data-members
|
||||
//
|
||||
template <class Data, class Class, class Policies>
|
||||
// A small function object which handles the getting and setting of
|
||||
// data members.
|
||||
template <class Data, class Class>
|
||||
struct member
|
||||
{
|
||||
static PyObject* get(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
arg_from_python<Class*> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
// find the result converter
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typedef typename boost::add_reference<Data>::type source;
|
||||
typename mpl::apply1<result_converter,source>::type cr;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = cr( (c0())->*pm );
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
|
||||
static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
arg_from_python<Class&> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
typedef typename add_const<Data>::type target1;
|
||||
typedef typename add_reference<target1>::type target;
|
||||
arg_from_python<target> c1(PyTuple_GET_ITEM(args_, 1));
|
||||
private:
|
||||
typedef typename add_const<Data>::type data_const;
|
||||
typedef typename add_reference<data_const>::type data_cref;
|
||||
|
||||
if (!c1.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
(c0()).*pm = c1();
|
||||
|
||||
return policies.postcall(args_, detail::none());
|
||||
public:
|
||||
member(Data Class::*which) : m_which(which) {}
|
||||
|
||||
Data& operator()(Class& c) const
|
||||
{
|
||||
return c.*m_which;
|
||||
}
|
||||
|
||||
void operator()(Class& c, data_cref d) const
|
||||
{
|
||||
c.*m_which = d;
|
||||
}
|
||||
private:
|
||||
Data Class::*m_which;
|
||||
};
|
||||
|
||||
//
|
||||
// Generates get and set functions for access through ordinary
|
||||
// pointers. These are generally used to wrap static data members,
|
||||
// but can also be used to expose namespace-scope data as class
|
||||
// attributes.
|
||||
//
|
||||
template <class Data, class Policies>
|
||||
// A small function object which handles the getting and setting of
|
||||
// non-member objects.
|
||||
template <class Data>
|
||||
struct datum
|
||||
{
|
||||
static PyObject* get(Data *p, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// find the result converter
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typedef typename boost::add_reference<Data>::type source;
|
||||
typename mpl::apply1<result_converter,source>::type cr;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = cr( *p );
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
|
||||
static PyObject* set(Data* p, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
typedef typename add_const<Data>::type target1;
|
||||
typedef typename add_reference<target1>::type target;
|
||||
arg_from_python<target> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
private:
|
||||
typedef typename add_const<Data>::type data_const;
|
||||
typedef typename add_reference<data_const>::type data_cref;
|
||||
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
*p = c0();
|
||||
|
||||
return policies.postcall(args_, detail::none());
|
||||
public:
|
||||
datum(Data *which) : m_which(which) {}
|
||||
|
||||
Data& operator()() const
|
||||
{
|
||||
return *m_which;
|
||||
}
|
||||
};
|
||||
|
||||
void operator()(data_cref d) const
|
||||
{
|
||||
*m_which = d;
|
||||
}
|
||||
private:
|
||||
Data *m_which;
|
||||
};
|
||||
|
||||
//
|
||||
// Helper metafunction for determining the default CallPolicy to use
|
||||
// for attribute access. If T is a [reference to a] class type X
|
||||
@@ -208,13 +170,8 @@ namespace detail
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D* d, Policies const& policies, mpl::false_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::datum<D,Policies>::get, d, _1, _2
|
||||
, policies)
|
||||
, mpl::vector1<D>()
|
||||
)
|
||||
return python::make_function(
|
||||
detail::datum<D>(d), policies, mpl::vector1<D&>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -230,14 +187,16 @@ namespace detail
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::get, pm, _1, _2
|
||||
, policies)
|
||||
, mpl::vector2<D, C const*>()
|
||||
)
|
||||
);
|
||||
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
typedef typename remove_cv<C>::type Class;
|
||||
#else
|
||||
typedef C Class;
|
||||
#endif
|
||||
return python::make_function(
|
||||
detail::member<D,Class>(pm)
|
||||
, policies
|
||||
, mpl::vector2<D&,Class&>()
|
||||
);
|
||||
}
|
||||
|
||||
// Handle pointers-to-members without policies
|
||||
@@ -268,13 +227,8 @@ namespace detail
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D* p, Policies const& policies, mpl::false_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::datum<D,Policies>::set, p, _1, _2
|
||||
, policies)
|
||||
, mpl::vector2<void, D const&>()
|
||||
)
|
||||
return python::make_function(
|
||||
detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -282,13 +236,10 @@ namespace detail
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int)
|
||||
{
|
||||
return objects::function_object(
|
||||
objects::py_function(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::set, pm, _1, _2
|
||||
, policies)
|
||||
, mpl::vector3<void, C*, D const&>()
|
||||
)
|
||||
return python::make_function(
|
||||
detail::member<D,C>(pm)
|
||||
, policies
|
||||
, mpl::vector3<void, C&, D const&>()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,14 +29,16 @@ struct default_result_converter;
|
||||
|
||||
struct default_call_policies
|
||||
{
|
||||
// Nothing to do
|
||||
static bool precall(PyObject*)
|
||||
// Ownership of this argument tuple will ultimately be adopted by
|
||||
// the caller.
|
||||
static PyObject* precall(PyObject* args_)
|
||||
{
|
||||
return true;
|
||||
Py_INCREF(args_);
|
||||
return args_;
|
||||
}
|
||||
|
||||
// Pass the result through
|
||||
static PyObject* postcall(PyObject*, PyObject* result)
|
||||
static PyObject* postcall(PyObject* args_, PyObject* result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/python/detail/invoke.hpp>
|
||||
# include <boost/python/detail/signature.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
@@ -147,15 +149,19 @@ struct caller_arity<N>
|
||||
# endif
|
||||
// all converters have been checked. Now we can do the
|
||||
// precall part of the policy
|
||||
if (!m_data.second().precall(args_))
|
||||
PyObject* inner_args = m_data.second().precall(args_);
|
||||
if (inner_args == 0)
|
||||
return 0;
|
||||
|
||||
// manage the inner arguments
|
||||
handle<> keeper(allow_null(inner_args));
|
||||
|
||||
typedef typename detail::invoke_tag<F>::type tag;
|
||||
|
||||
PyObject* result = detail::invoke(
|
||||
tag(), result_converter(), m_data.first() BOOST_PP_ENUM_TRAILING_PARAMS(N, c));
|
||||
|
||||
return m_data.second().postcall(args_, result);
|
||||
return m_data.second().postcall(inner_args, result);
|
||||
}
|
||||
|
||||
static unsigned min_arity() { return N; }
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace boost { namespace python { namespace detail {
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
template <class R, class T>
|
||||
boost::type<T*>* target(R (T::*)) { return 0; }
|
||||
T& (* target(R (T::*)) )() { return 0; }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
@@ -44,7 +44,7 @@ boost::type<T*>* target(R (T::*)) { return 0; }
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <class R BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)>
|
||||
boost::type<BOOST_PP_IF(N, A0, void)>* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)))
|
||||
BOOST_PP_IF(N, A0, void)(* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A))) )()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ boost::type<BOOST_PP_IF(N, A0, void)>* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N,
|
||||
# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1))
|
||||
|
||||
template <class R, class T BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)>
|
||||
boost::type<T Q*>* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q)
|
||||
T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -393,13 +393,13 @@ namespace detail
|
||||
template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
|
||||
static void apply(
|
||||
ClassT& cl
|
||||
, CallPoliciesT const& policies
|
||||
, Signature const& args
|
||||
, NArgs
|
||||
, char const* doc
|
||||
, detail::keyword_range const& keywords)
|
||||
, CallPoliciesT const& policies
|
||||
, Signature const& args
|
||||
, NArgs
|
||||
, char const* doc
|
||||
, detail::keyword_range const& keywords)
|
||||
{
|
||||
def_init_aux(cl, args, NArgs(), policies, doc, keywords);
|
||||
detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
# include <boost/python/detail/target.hpp>
|
||||
# include <boost/python/object/iterator.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/bind/protect.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
@@ -21,14 +25,19 @@ namespace detail
|
||||
// Adds an additional layer of binding to
|
||||
// objects::make_iterator(...), which allows us to pass member
|
||||
// function and member data pointers.
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
template <class Target, class Accessor1, class Accessor2, class NextPolicies>
|
||||
inline object make_iterator(
|
||||
Accessor1 get_start, Accessor2 get_finish, boost::type<Target>* target = 0, NextPolicies* = 0)
|
||||
Accessor1 get_start
|
||||
, Accessor2 get_finish
|
||||
, NextPolicies next_policies
|
||||
, Target&(*)()
|
||||
)
|
||||
{
|
||||
return objects::make_iterator_function<NextPolicies,Target>(
|
||||
return objects::make_iterator_function<Target>(
|
||||
boost::protect(boost::bind(get_start, _1))
|
||||
, boost::protect(boost::bind(get_finish, _1))
|
||||
);
|
||||
, boost::protect(boost::bind(get_finish, _1))
|
||||
, next_policies
|
||||
);
|
||||
}
|
||||
|
||||
// Guts of template class iterators<>, below.
|
||||
@@ -73,9 +82,11 @@ struct iterators
|
||||
template <class Accessor1, class Accessor2>
|
||||
object range(Accessor1 start, Accessor2 finish)
|
||||
{
|
||||
return detail::make_iterator<objects::default_iterator_call_policies>(
|
||||
start, finish
|
||||
, detail::target(start));
|
||||
return detail::make_iterator(
|
||||
start, finish
|
||||
, objects::default_iterator_call_policies()
|
||||
, detail::target(start)
|
||||
);
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
@@ -83,7 +94,7 @@ object range(Accessor1 start, Accessor2 finish)
|
||||
template <class NextPolicies, class Accessor1, class Accessor2>
|
||||
object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0)
|
||||
{
|
||||
return detail::make_iterator<NextPolicies>(start, finish, detail::target(start));
|
||||
return detail::make_iterator(start, finish, NextPolicies(), detail::target(start));
|
||||
}
|
||||
|
||||
// Create an iterator-building function which uses the given accessors
|
||||
@@ -91,8 +102,8 @@ object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0)
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type<Target>* = 0)
|
||||
{
|
||||
typedef typename add_reference<Target>::type target;
|
||||
return detail::make_iterator<NextPolicies, target>(start, finish);
|
||||
// typedef typename add_reference<Target>::type target;
|
||||
return detail::make_iterator(start, finish, NextPolicies(), (Target&(*)())0);
|
||||
}
|
||||
|
||||
// A Python callable object which produces an iterator traversing
|
||||
|
||||
@@ -6,20 +6,26 @@
|
||||
#ifndef ITERATOR_DWA2002510_HPP
|
||||
# define ITERATOR_DWA2002510_HPP
|
||||
|
||||
# include <boost/python/object/iterator_core.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/class.hpp>
|
||||
# include <boost/python/object/class_detail.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/return_by_value.hpp>
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
|
||||
# include <boost/python/object/iterator_core.hpp>
|
||||
# include <boost/python/object/class_detail.hpp>
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
|
||||
# include <boost/mpl/vector/vector10.hpp>
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/bind/protect.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/add_const.hpp>
|
||||
|
||||
@@ -40,6 +46,62 @@ struct iterator_range
|
||||
{
|
||||
iterator_range(object sequence, Iterator start, Iterator finish);
|
||||
|
||||
typedef boost::detail::iterator_traits<Iterator> traits_t;
|
||||
|
||||
struct next
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
is_reference<
|
||||
typename traits_t::reference
|
||||
>
|
||||
, typename traits_t::reference
|
||||
, typename traits_t::value_type
|
||||
>::type result_type;
|
||||
|
||||
result_type
|
||||
operator()(iterator_range<NextPolicies,Iterator>& self)
|
||||
{
|
||||
if (self.m_start == self.m_finish)
|
||||
stop_iteration_error();
|
||||
return *self.m_start++;
|
||||
}
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
// CWPro8 has a codegen problem when this is an empty class
|
||||
int garbage;
|
||||
# endif
|
||||
};
|
||||
|
||||
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// for compilers which can't deduce the value_type of pointers, we
|
||||
// have a special implementation of next. This takes advantage of
|
||||
// the fact that T* results are treated like T& results by
|
||||
// Boost.Python's function wrappers.
|
||||
struct next_ptr
|
||||
{
|
||||
typedef Iterator result_type;
|
||||
|
||||
result_type
|
||||
operator()(iterator_range<NextPolicies,Iterator>& self)
|
||||
{
|
||||
if (self.m_start == self.m_finish)
|
||||
stop_iteration_error();
|
||||
return self.m_start++;
|
||||
}
|
||||
};
|
||||
|
||||
typedef mpl::if_<
|
||||
is_same<
|
||||
boost::detail::please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<Iterator>
|
||||
, typename traits_t::value_type
|
||||
>
|
||||
, next_ptr
|
||||
, next
|
||||
>::type next_fn;
|
||||
# else
|
||||
typedef next next_fn;
|
||||
# endif
|
||||
|
||||
object m_sequence; // Keeps the sequence alive while iterating.
|
||||
Iterator m_start;
|
||||
Iterator m_finish;
|
||||
@@ -47,62 +109,6 @@ struct iterator_range
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Guts of the iterator's next() function. We can't just wrap an
|
||||
// ordinary function because we don't neccessarily know the result
|
||||
// type of dereferencing the iterator. This also saves us from
|
||||
// throwing C++ exceptions to indicate end-of-sequence.
|
||||
template <class Iterator, class Policies>
|
||||
struct iterator_next
|
||||
{
|
||||
static PyObject* execute(PyObject* args_, PyObject* kw, Policies const& policies)
|
||||
{
|
||||
typedef iterator_range<Policies,Iterator> range_;
|
||||
|
||||
PyObject* py_self = PyTuple_GET_ITEM(args_, 0);
|
||||
arg_from_python<range_*> c0(py_self);
|
||||
range_* self = c0();
|
||||
|
||||
// Done iterating?
|
||||
if (self->m_start == self->m_finish)
|
||||
{
|
||||
objects::set_stop_iteration_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// note: precall happens before we can check for the result
|
||||
// converter in this case, to ensure it happens before the
|
||||
// iterator is dereferenced. However, the arity is 1 so
|
||||
// there's not much risk that this will amount to anything.
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = iterator_next::convert_result(*self->m_start);
|
||||
++self->m_start;
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
private:
|
||||
// Convert the result of dereferencing the iterator. Dispatched
|
||||
// here because we can't neccessarily get the value_type of the
|
||||
// iterator without PTS. This way, we deduce the value type by
|
||||
// dereferencing.
|
||||
template <class ValueType>
|
||||
static PyObject* convert_result(ValueType& x)
|
||||
{
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typename mpl::apply1<result_converter,ValueType&>::type cr;
|
||||
|
||||
return cr(x);
|
||||
}
|
||||
template <class ValueType>
|
||||
static PyObject* convert_result(ValueType const& x)
|
||||
{
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typename mpl::apply1<result_converter,ValueType const&>::type cr;
|
||||
|
||||
return cr(x);
|
||||
}
|
||||
};
|
||||
|
||||
// Get a Python class which contains the given iterator and
|
||||
// policies, creating it if neccessary. Requires: NextPolicies is
|
||||
// default-constructible.
|
||||
@@ -118,93 +124,90 @@ namespace detail
|
||||
if (class_obj.get() != 0)
|
||||
return object(class_obj);
|
||||
|
||||
// Make a callable object which can be used as the iterator's next() function.
|
||||
object next_function =
|
||||
objects::function_object(
|
||||
py_function(
|
||||
bind(&detail::iterator_next<Iterator,NextPolicies>::execute, _1, _2, policies)
|
||||
, mpl::vector2<
|
||||
# if defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
object
|
||||
# else
|
||||
typename boost::detail::iterator_traits<Iterator>::value_type
|
||||
# endif
|
||||
, Iterator
|
||||
>()
|
||||
)
|
||||
);
|
||||
|
||||
typedef typename range_::next_fn next_fn;
|
||||
typedef typename next_fn::result_type result_type;
|
||||
|
||||
return class_<range_>(name, no_init)
|
||||
.def("__iter__", identity_function())
|
||||
.setattr("next", next_function)
|
||||
;
|
||||
.def(
|
||||
"next"
|
||||
, make_function(
|
||||
next_fn()
|
||||
, policies
|
||||
, mpl::vector2<result_type,range_&>()
|
||||
));
|
||||
}
|
||||
|
||||
// This class template acts as a generator for an ordinary function
|
||||
// which builds a Python iterator.
|
||||
template <class Target, class Iterator
|
||||
, class Accessor1, class Accessor2
|
||||
, class NextPolicies
|
||||
>
|
||||
struct make_iterator_help
|
||||
// A function object which builds an iterator_range.
|
||||
template <
|
||||
class Target
|
||||
, class Iterator
|
||||
, class Accessor1
|
||||
, class Accessor2
|
||||
, class NextPolicies
|
||||
>
|
||||
struct py_iter_
|
||||
{
|
||||
py_iter_(Accessor1 const& get_start, Accessor2 const& get_finish)
|
||||
: m_get_start(get_start)
|
||||
, m_get_finish(get_finish)
|
||||
{}
|
||||
|
||||
// Extract an object x of the Target type from the first Python
|
||||
// argument, and invoke get_start(x)/get_finish(x) to produce
|
||||
// iterators, which are used to construct a new iterator_range<>
|
||||
// object that gets wrapped into a Python iterator.
|
||||
static PyObject* create(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish
|
||||
, PyObject* args_, PyObject* /*kw*/)
|
||||
iterator_range<NextPolicies,Iterator>
|
||||
operator()(back_reference<Target&> x) const
|
||||
{
|
||||
// Make sure the Python class is instantiated.
|
||||
detail::demand_iterator_class("iterator", (Iterator*)0, NextPolicies());
|
||||
|
||||
to_python_value<iterator_range<NextPolicies,Iterator> > cr;
|
||||
|
||||
// Extract x from the first argument
|
||||
PyObject* arg0 = PyTuple_GET_ITEM(args_, 0);
|
||||
arg_from_python<Target> c0(arg0);
|
||||
if (!c0.convertible()) return 0;
|
||||
typename arg_from_python<Target>::result_type x = c0();
|
||||
|
||||
// Build and convert the iterator_range<>.
|
||||
return cr(
|
||||
iterator_range<NextPolicies,Iterator>(
|
||||
object((python::detail::borrowed_reference)arg0)
|
||||
, get_start(x), get_finish(x)));
|
||||
|
||||
return iterator_range<NextPolicies,Iterator>(
|
||||
x.source()
|
||||
, m_get_start(x.get())
|
||||
, m_get_finish(x.get())
|
||||
);
|
||||
}
|
||||
private:
|
||||
Accessor1 m_get_start;
|
||||
Accessor2 m_get_finish;
|
||||
};
|
||||
|
||||
template <class NextPolicies, class Target, class Iterator, class Accessor1, class Accessor2>
|
||||
template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
|
||||
inline object make_iterator_function(
|
||||
Accessor1 const& get_start
|
||||
, Accessor2 const& get_finish
|
||||
, NextPolicies const& next_policies
|
||||
, Iterator const& (*)()
|
||||
, boost::type<Target>*
|
||||
, NextPolicies*
|
||||
, int
|
||||
)
|
||||
{
|
||||
return
|
||||
objects::function_object(
|
||||
py_function(
|
||||
boost::bind(
|
||||
&make_iterator_help<
|
||||
Target,Iterator,Accessor1,Accessor2,NextPolicies
|
||||
>::create
|
||||
, get_start, get_finish, _1, _2)
|
||||
, mpl::vector2<object, Target>()
|
||||
)
|
||||
);
|
||||
return make_function(
|
||||
py_iter_<Target,Iterator,Accessor1,Accessor2,NextPolicies>(get_start, get_finish)
|
||||
, default_call_policies()
|
||||
, mpl::vector2<iterator_range<NextPolicies,Iterator>, back_reference<Target&> >()
|
||||
);
|
||||
}
|
||||
|
||||
template <class NextPolicies, class Target, class Iterator, class Accessor1, class Accessor2>
|
||||
template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2>
|
||||
inline object make_iterator_function(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish, Iterator& (*)(), boost::type<Target>*, NextPolicies*, ...)
|
||||
Accessor1 const& get_start
|
||||
, Accessor2 const& get_finish
|
||||
, NextPolicies const& next_policies
|
||||
, Iterator& (*)()
|
||||
, boost::type<Target>*
|
||||
, ...)
|
||||
{
|
||||
return make_iterator_function(
|
||||
get_start, get_finish, (Iterator const&(*)())0
|
||||
, (boost::type<Target>*)0, (NextPolicies*)0, 0);
|
||||
get_start
|
||||
, get_finish
|
||||
, next_policies
|
||||
, (Iterator const&(*)())0
|
||||
, (boost::type<Target>*)0
|
||||
, 0
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -215,22 +218,26 @@ namespace detail
|
||||
// (where x is an instance of Target) to produce begin and end
|
||||
// iterators for the range, and an instance of NextPolicies is used as
|
||||
// CallPolicies for the Python iterator's next() function.
|
||||
template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
||||
template <class Target, class NextPolicies, class Accessor1, class Accessor2>
|
||||
inline object make_iterator_function(
|
||||
Accessor1 const& get_start, Accessor2 const& get_finish
|
||||
, boost::type<Target>* = 0, NextPolicies* = 0)
|
||||
Accessor1 const& get_start
|
||||
, Accessor2 const& get_finish
|
||||
, NextPolicies const& next_policies
|
||||
, boost::type<Target>* = 0
|
||||
)
|
||||
{
|
||||
typedef typename Accessor1::result_type iterator;
|
||||
typedef typename add_const<iterator>::type iterator_const;
|
||||
typedef typename add_reference<iterator_const>::type iterator_cref;
|
||||
|
||||
return detail::make_iterator_function(
|
||||
get_start, get_finish
|
||||
, (iterator_cref(*)())0
|
||||
, (boost::type<Target>*)0
|
||||
, (NextPolicies*)0
|
||||
, 0
|
||||
);
|
||||
get_start
|
||||
, get_finish
|
||||
, next_policies
|
||||
, (iterator_cref(*)())0
|
||||
, (boost::type<Target>*)0
|
||||
, 0
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
BOOST_PYTHON_DECL object const& identity_function();
|
||||
BOOST_PYTHON_DECL void set_stop_iteration_error();
|
||||
BOOST_PYTHON_DECL void stop_iteration_error();
|
||||
|
||||
}}} // namespace boost::python::object
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace boost { namespace python {
|
||||
template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies>
|
||||
struct with_custodian_and_ward : BasePolicy_
|
||||
{
|
||||
static bool precall(PyObject* args);
|
||||
static PyObject* precall(PyObject* args);
|
||||
};
|
||||
|
||||
template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies>
|
||||
@@ -29,31 +29,39 @@ struct with_custodian_and_ward_postcall : BasePolicy_
|
||||
// implementations
|
||||
//
|
||||
template <std::size_t custodian, std::size_t ward, class BasePolicy_>
|
||||
bool with_custodian_and_ward<custodian,ward,BasePolicy_>::precall(PyObject* args_)
|
||||
PyObject*
|
||||
with_custodian_and_ward<custodian,ward,BasePolicy_>::precall(
|
||||
PyObject* args_
|
||||
)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(custodian != ward);
|
||||
BOOST_STATIC_ASSERT(custodian > 0);
|
||||
BOOST_STATIC_ASSERT(ward > 0);
|
||||
|
||||
PyObject* patient = PyTuple_GetItem(args_, ward - 1);
|
||||
if (patient == 0) return false;
|
||||
if (patient == 0)
|
||||
return 0;
|
||||
|
||||
PyObject* nurse = PyTuple_GetItem(args_, custodian - 1);
|
||||
if (nurse == 0) return false;
|
||||
if (nurse == 0)
|
||||
return 0;
|
||||
|
||||
PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient);
|
||||
if (life_support == 0)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
bool result = BasePolicy_::precall(args_);
|
||||
|
||||
if (!result)
|
||||
args_ = BasePolicy_::precall(args_);
|
||||
if (args_ == 0)
|
||||
Py_XDECREF(life_support);
|
||||
|
||||
return result;
|
||||
return args_;
|
||||
}
|
||||
|
||||
template <std::size_t custodian, std::size_t ward, class BasePolicy_>
|
||||
PyObject* with_custodian_and_ward_postcall<custodian,ward,BasePolicy_>::postcall(PyObject* args_, PyObject* result)
|
||||
PyObject*
|
||||
with_custodian_and_ward_postcall<custodian,ward,BasePolicy_>::postcall(
|
||||
PyObject* args_
|
||||
, PyObject* result)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(custodian != ward);
|
||||
|
||||
|
||||
@@ -31,9 +31,10 @@ BOOST_PYTHON_DECL object const& identity_function()
|
||||
return result;
|
||||
}
|
||||
|
||||
void set_stop_iteration_error()
|
||||
void stop_iteration_error()
|
||||
{
|
||||
PyErr_SetObject(PyExc_StopIteration, Py_None);
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
@@ -101,12 +101,7 @@ BOOST_PYTHON_MODULE(data_members_ext)
|
||||
|
||||
class_<Var>("Var", init<std::string>())
|
||||
.def_readonly("name", &Var::name)
|
||||
.def_readonly("name2",
|
||||
#if __MWERKS__ <= 0x2407 // Old MWerks mis-deduces the type here as `char* Var::*'
|
||||
(char const* Var::*)
|
||||
#endif
|
||||
&Var::name2
|
||||
)
|
||||
.def_readonly("name2", &Var::name2)
|
||||
.def_readwrite("value", &Var::value)
|
||||
.def_readonly("y", &Var::y)
|
||||
|
||||
|
||||
@@ -13,30 +13,17 @@
|
||||
# pragma ANSI_strict reset
|
||||
# endif
|
||||
|
||||
extern "C" BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved );
|
||||
|
||||
# ifdef BOOST_MSVC
|
||||
# ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4297)
|
||||
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
|
||||
extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*)
|
||||
= _set_se_translator(straight_to_debugger);
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
BOOL WINAPI DllMain(
|
||||
HINSTANCE, //hDllInst
|
||||
DWORD fdwReason,
|
||||
LPVOID // lpvReserved
|
||||
)
|
||||
{
|
||||
# ifdef BOOST_MSVC
|
||||
_set_se_translator(structured_exception_translator);
|
||||
# endif
|
||||
(void)fdwReason; // warning suppression.
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ handle<> return_null_handle()
|
||||
|
||||
char const* rewrap_value_mutable_cstring(char* x) { return x; }
|
||||
|
||||
object identity_(object x) { return x; }
|
||||
|
||||
BOOST_PYTHON_MODULE(builtin_converters)
|
||||
{
|
||||
def("get_type", get_type);
|
||||
@@ -83,8 +85,20 @@ BOOST_PYTHON_MODULE(builtin_converters)
|
||||
def("rewrap_value_complex_float", by_value<std::complex<float> >::rewrap);
|
||||
def("rewrap_value_complex_double", by_value<std::complex<double> >::rewrap);
|
||||
def("rewrap_value_complex_long_double", by_value<std::complex<long double> >::rewrap);
|
||||
def("rewrap_value_wstring", by_value<std::wstring>::rewrap);
|
||||
def("rewrap_value_string", by_value<std::wstring>::rewrap);
|
||||
def("rewrap_value_wstring",
|
||||
# ifdef BOOST_NO_STD_WSTRING
|
||||
identity_
|
||||
# else
|
||||
by_value<std::wstring>::rewrap
|
||||
# endif
|
||||
);
|
||||
def("rewrap_value_string",
|
||||
# ifdef BOOST_NO_STD_WSTRING
|
||||
identity_
|
||||
# else
|
||||
by_value<std::wstring>::rewrap
|
||||
# endif
|
||||
);
|
||||
def("rewrap_value_string", by_value<std::string>::rewrap);
|
||||
def("rewrap_value_cstring", by_value<char const*>::rewrap);
|
||||
def("rewrap_value_handle", by_value<handle<> >::rewrap);
|
||||
|
||||
Reference in New Issue
Block a user