2
0
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:
Dave Abrahams
2003-09-17 21:36:53 +00:00
parent db192e1e01
commit bec2de08fe
14 changed files with 292 additions and 308 deletions

View File

@@ -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))

View File

@@ -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&>()
);
}

View File

@@ -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;
}

View File

@@ -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; }

View File

@@ -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;
}

View File

@@ -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);
}
};
}

View File

@@ -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

View File

@@ -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
);
}
//

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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);