2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-25 06:22:15 +00:00

Implemented injected constructors.

Eliminated _DEBUG redefinition warning for CWPro8.


[SVN r20126]
This commit is contained in:
Dave Abrahams
2003-09-21 01:35:19 +00:00
parent 4f2dbeda28
commit 92a77dfe7f
11 changed files with 566 additions and 129 deletions

View File

@@ -0,0 +1,18 @@
// Copyright David Abrahams 2003. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
# define CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
namespace boost { namespace python { namespace converter {
// A ResultConverter base class used to indicate that this result
// converter should be constructed with the original Python argument
// list.
struct context_result_converter {};
}}} // namespace boost::python::converter
#endif // CONTEXT_RESULT_CONVERTER_DWA2003917_HPP

View File

@@ -31,19 +31,21 @@ struct default_call_policies
{
// Ownership of this argument tuple will ultimately be adopted by
// the caller.
static PyObject* precall(PyObject* args_)
template <class ArgumentPackage>
static bool precall(ArgumentPackage const&)
{
Py_INCREF(args_);
return args_;
return true;
}
// Pass the result through
static PyObject* postcall(PyObject* args_, PyObject* result)
template <class ArgumentPackage>
static PyObject* postcall(ArgumentPackage const&, PyObject* result)
{
return result;
}
typedef default_result_converter result_converter;
typedef PyObject* argument_package;
};
struct default_result_converter

View File

@@ -9,14 +9,6 @@
# ifndef CALLER_DWA20021121_HPP
# define CALLER_DWA20021121_HPP
# include <boost/compressed_pair.hpp>
# include <boost/mpl/apply.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/size.hpp>
# include <boost/mpl/at.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/handle.hpp>
@@ -25,6 +17,7 @@
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/arg_from_python.hpp>
# include <boost/python/converter/context_result_converter.hpp>
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/cat.hpp>
@@ -34,8 +27,39 @@
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
# include <boost/preprocessor/repetition/repeat.hpp>
# include <boost/compressed_pair.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/mpl/apply.hpp>
# include <boost/mpl/apply_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/size.hpp>
# include <boost/mpl/at.hpp>
# include <boost/mpl/int.hpp>
namespace boost { namespace python { namespace detail {
# if 0 // argpkg
template <class N>
inline PyObject* get(N, PyObject* const& args_)
{
return PyTuple_GET_ITEM(args_,N::value);
}
# else
template <unsigned N>
inline PyObject* get(PyObject* const& args_ BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(unsigned,N))
{
return PyTuple_GET_ITEM(args_,N);
}
# endif
inline unsigned arity(PyObject* const& args_)
{
return PyTuple_GET_SIZE(args_);
}
// This "result converter" is really just used as
// a dispatch tag to invoke(...), selecting the appropriate
// implementation
@@ -46,15 +70,34 @@ typedef int void_result_to_python;
// converting the result to python.
template <class Policies, class Result>
struct select_result_converter
: mpl::if_<
: mpl::apply_if<
is_same<Result,void>
, void_result_to_python
, typename mpl::apply1<typename Policies::result_converter,Result>::type*
, mpl::identity<void_result_to_python>
, mpl::apply1<typename Policies::result_converter,Result>
>
{
};
template <class ArgPackage, class ResultConverter>
inline ResultConverter create_result_converter(
ArgPackage const& args_
, ResultConverter*
, converter::context_result_converter*
)
{
return ResultConverter(args_);
}
template <class ArgPackage, class ResultConverter>
inline ResultConverter create_result_converter(
ArgPackage const& args_
, ResultConverter*
, ...
)
{
return ResultConverter();
}
template <unsigned> struct caller_arity;
template <class F, class CallPolicies, class Sig>
@@ -63,12 +106,21 @@ struct caller;
# define BOOST_PYTHON_NEXT(init,name,n) \
typedef BOOST_PP_IF(n,typename BOOST_PP_CAT(name,BOOST_PP_DEC(n)) ::next, init) name##n;
# if 0 // argpkg
# define BOOST_PYTHON_ARG_CONVERTER(n) \
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \
c_t##n c##n(PyTuple_GET_ITEM(args_, n)); \
c_t##n c##n(get(mpl::int_<n>(), inner_args)); \
if (!c##n.convertible()) \
return 0;
# else
# define BOOST_PYTHON_ARG_CONVERTER(n) \
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \
c_t##n c##n(get<n>(inner_args)); \
if (!c##n.convertible()) \
return 0;
# endif
# define BOOST_PP_ITERATION_PARAMS_1 \
(3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/caller.hpp>))
@@ -142,6 +194,10 @@ struct caller_arity<N>
typedef typename mpl::begin<Sig>::type first;
typedef typename first::type result_t;
typedef typename select_result_converter<Policies, result_t>::type result_converter;
typedef typename Policies::argument_package argument_package;
argument_package inner_args(args_);
# if N
# define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i)
# define BOOST_PP_LOCAL_LIMITS (0, N-1)
@@ -149,17 +205,15 @@ struct caller_arity<N>
# endif
// all converters have been checked. Now we can do the
// precall part of the policy
PyObject* inner_args = m_data.second().precall(args_);
if (inner_args == 0)
if (!m_data.second().precall(inner_args))
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));
detail::invoke_tag<result_t,F>()
, create_result_converter(args_, (result_converter*)0, (result_converter*)0)
, m_data.first()
BOOST_PP_ENUM_TRAILING_PARAMS(N, c)
);
return m_data.second().postcall(inner_args, result);
}

View File

@@ -45,23 +45,19 @@ namespace boost { namespace python { namespace detail {
// invoke(...), selecting the appropriate implementation
typedef int void_result_to_python;
// Trait forward declaration.
template <class T> struct is_defaulted_virtual_fn;
// Tag types describing invocation methods
struct fn_tag {};
struct mem_fn_tag {};
template <bool void_return, bool member>
struct invoke_tag_ {};
// A metafunction returning the appropriate tag type for invoking an
// object of type T.
template <class T>
// object of type F with return type R.
template <class R, class F>
struct invoke_tag
: mpl::if_<
is_member_function_pointer<T>
, mem_fn_tag
, fn_tag
: invoke_tag_<
is_same<R,void>::value
, is_member_function_pointer<F>::value
>
{};
{
};
# define BOOST_PP_ITERATION_PARAMS_1 \
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/invoke.hpp>))
@@ -75,26 +71,26 @@ struct invoke_tag
# define N BOOST_PP_ITERATION()
template <class RC, class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
inline PyObject* invoke(fn_tag, RC*, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
inline PyObject* invoke(invoke_tag_<false,false>, RC const& rc, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
{
return RC()(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ));
return rc(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ));
}
template <class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
inline PyObject* invoke(fn_tag, void_result_to_python, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
template <class RC, class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
inline PyObject* invoke(invoke_tag_<true,false>, RC const&, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
{
f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) );
return none();
}
template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
inline PyObject* invoke(mem_fn_tag, RC*, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
inline PyObject* invoke(invoke_tag_<false,true>, RC const& rc, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
{
return RC()( (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)) );
return rc( (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)) );
}
template <class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
inline PyObject* invoke(mem_fn_tag, void_result_to_python, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)>
inline PyObject* invoke(invoke_tag_<true,true>, RC const&, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
{
(tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT));
return none();

View File

@@ -9,15 +9,16 @@
# ifndef SIGNATURE_DWA20021121_HPP
# define SIGNATURE_DWA20021121_HPP
# include <boost/mpl/at.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/iteration/local.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/at.hpp>
# include <boost/mpl/size.hpp>
namespace boost { namespace python { namespace detail {

View File

@@ -0,0 +1,283 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_CONSTRUCTOR_DWA20011221_HPP
# define MAKE_CONSTRUCTOR_DWA20011221_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/default_call_policies.hpp>
# include <boost/python/args.hpp>
# include <boost/python/object_fwd.hpp>
# include <boost/python/object/function_object.hpp>
# include <boost/python/object/make_holder.hpp>
# include <boost/python/object/pointer_holder.hpp>
# include <boost/python/converter/context_result_converter.hpp>
# include <boost/python/detail/caller.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/mpl/size.hpp>
# include <boost/mpl/int.hpp>
# include <boost/mpl/push_front.hpp>
# include <boost/mpl/pop_front.hpp>
namespace boost { namespace python {
namespace detail
{
template <class T>
struct install_holder : converter::context_result_converter
{
install_holder(PyObject* args_)
: m_self(PyTuple_GetItem(args_, 0)) {}
PyObject* operator()(T x) const
{
dispatch(x, is_pointer<T>());
return none();
}
private:
template <class U>
void dispatch(U* x, mpl::true_) const
{
std::auto_ptr<U> owner(x);
dispatch(owner, mpl::false_());
}
template <class Ptr>
void dispatch(Ptr x, mpl::false_) const
{
typedef typename pointee<Ptr>::type value_type;
typedef objects::pointer_holder<Ptr,value_type> holder;
typedef objects::instance<holder> instance_t;
void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder));
try {
(new (memory) holder(x))->install(this->m_self);
}
catch(...) {
holder::deallocate(this->m_self, memory);
throw;
}
}
PyObject* m_self;
};
struct constructor_result_converter
{
template <class T>
struct apply
{
typedef install_holder<T> type;
};
};
template <class BaseArgs, class Offset>
struct offset_args
{
offset_args(BaseArgs base_) : base(base_) {}
BaseArgs base;
};
# if 0
template <class N, class BaseArgs, class Offset>
inline PyObject* get(N, offset_args<BaseArgs,Offset> const& args_)
{
return get(mpl::int_<(N::value+Offset::value)>(), args_.base);
}
# else
template <unsigned N, class BaseArgs, class Offset>
inline PyObject* get(offset_args<BaseArgs,Offset> const& args_ BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(unsigned,N))
{
return get<(N + Offset::value)>(args_.base);
}
# endif
template <class BaseArgs, class Offset>
inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)
{
return arity(args_.base) - Offset::value;
}
template <class BasePolicy_ = default_call_policies>
struct constructor_policy : BasePolicy_
{
constructor_policy(BasePolicy_ base) : BasePolicy_(base) {}
// If the BasePolicy_ supplied a result converter it would be
// ignored; issue an error if it's not the default.
BOOST_STATIC_ASSERT((
is_same<
typename BasePolicy_::result_converter
, default_result_converter
>::value
));
typedef constructor_result_converter result_converter;
typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
};
template <class InnerSignature>
struct outer_constructor_signature
{
typedef typename mpl::pop_front<InnerSignature>::type inner_args;
typedef typename mpl::push_front<inner_args,object>::type outer_args;
typedef typename mpl::push_front<outer_args,void>::type type;
};
// ETI workaround
template <>
struct outer_constructor_signature<int>
{
typedef int type;
};
// { make_constructor_aux
//
// These helper functions for make_constructor (below) do the raw work
// of constructing a Python object from some invokable entity. See
// <boost/python/detail/caller.hpp> for more information about how
// the Sig arguments is used.
template <class F, class CallPolicies, class Sig>
object make_constructor_aux(
F f // An object that can be invoked by detail::invoke()
, CallPolicies const& p // CallPolicies to use in the invocation
, Sig const& // An MPL sequence of argument types expected by F
)
{
typedef typename outer_constructor_signature<Sig>::type outer_signature;
typedef constructor_policy<CallPolicies> inner_policy;
return objects::function_object(
objects::py_function(
detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
, outer_signature()
)
);
}
// As above, except that it accepts argument keywords. NumKeywords
// is used only for a compile-time assertion to make sure the user
// doesn't pass more keywords than the function can accept. To
// disable all checking, pass mpl::int_<0> for NumKeywords.
template <class F, class CallPolicies, class Sig, class NumKeywords>
object make_constructor_aux(
F f
, CallPolicies const& p
, Sig const&
, detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names
, NumKeywords // An MPL integral type wrapper: the size of kw
)
{
enum { arity = mpl::size<Sig>::value - 1 };
typedef typename detail::error::more_keywords_than_function_arguments<
NumKeywords::value, arity
>::too_many_keywords assertion;
typedef typename outer_constructor_signature<Sig>::type outer_signature;
typedef constructor_policy<CallPolicies> inner_policy;
return objects::function_object(
objects::py_function(
detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
, outer_signature()
)
);
}
// }
// { Helpers for make_constructor when called with 3 arguments. These
// dispatch functions are used to discriminate between the cases
// when the 3rd argument is keywords or when it is a signature.
//
template <class F, class CallPolicies, class Keywords>
object make_constructor_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
{
return detail::make_constructor_aux(
f
, policies
, detail::get_signature(f)
, kw.range()
, mpl::int_<Keywords::size>()
);
}
template <class F, class CallPolicies, class Signature>
object make_constructor_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
{
return detail::make_constructor_aux(
f
, policies
, sig
);
}
// }
}
// { These overloaded functions wrap a function or member function
// pointer as a Python object, using optional CallPolicies,
// Keywords, and/or Signature.
template <class F>
object make_constructor(F f)
{
return detail::make_constructor_aux(
f,default_call_policies(), detail::get_signature(f));
}
template <class F, class CallPolicies>
object make_constructor(F f, CallPolicies const& policies)
{
return detail::make_constructor_aux(
f, policies, detail::get_signature(f));
}
template <class F, class CallPolicies, class KeywordsOrSignature>
object make_constructor(
F f
, CallPolicies const& policies
, KeywordsOrSignature const& keywords_or_signature)
{
typedef typename
detail::is_reference_to_keywords<KeywordsOrSignature&>::type
is_kw;
return detail::make_constructor_dispatch(
f
, policies
, keywords_or_signature
, is_kw()
);
}
template <class F, class CallPolicies, class Keywords, class Signature>
object make_constructor(
F f
, CallPolicies const& policies
, Keywords const& kw
, Signature const& sig
)
{
return detail::make_constructor_aux(
f
, policies
, sig
, kw.range()
, mpl::int_<Keywords::size>()
);
}
// }
}}
#endif // MAKE_CONSTRUCTOR_DWA20011221_HPP

View File

@@ -7,10 +7,17 @@
# define RETURN_ARG_DWA2003719_HPP
# include <boost/python/default_call_policies.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/type_traits/add_reference.hpp>
# include <boost/type_traits/add_const.hpp>
# if 0 // argpkg
# include <boost/mpl/int.hpp>
# endif
# include <boost/static_assert.hpp>
# include <boost/python/refcount.hpp>
# include <cstddef>
namespace boost { namespace python {
@@ -67,8 +74,24 @@ struct return_arg : Base
// think it is better to issue an error instead, cause it can
// lead to confusions
>::type result_converter;
static PyObject* postcall(PyObject *args, PyObject* result);
template <class ArgumentPackage>
static PyObject* postcall(ArgumentPackage const& args, PyObject* result)
{
// In case of arg_pos == 0 we could simply return Base::postcall,
// but this is redundant
BOOST_STATIC_ASSERT(arg_pos > 0);
result = Base::postcall(args,result);
if (!result)
return 0;
Py_DECREF(result);
# if 0 // argpkg
return incref( detail::get(mpl::int_<arg_pos-1>(),args) );
# else
return incref( detail::get<(arg_pos-1)>(args) );
# endif
}
};
template <
@@ -78,23 +101,6 @@ struct return_self
: return_arg<1,Base>
{};
template <size_t arg_pos, class Base>
inline PyObject*
return_arg<arg_pos, Base>::postcall(PyObject *args, PyObject* result)
{
// In case of arg_pos == 0 we could simply return Base::postcall,
// but this is redundant
BOOST_STATIC_ASSERT(arg_pos > 0);
handle<> base_result(Base::postcall(args,result));
if(!base_result)
return 0;
return incref(PyTuple_GetItem(args,arg_pos-1));
}
}} // namespace boost::python
#endif // RETURN_ARG_DWA2003719_HPP

View File

@@ -10,78 +10,94 @@
# include <boost/python/default_call_policies.hpp>
# include <boost/python/object/life_support.hpp>
# include <algorithm>
namespace boost { namespace python {
template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies>
template <
std::size_t custodian
, std::size_t ward
, class BasePolicy_ = default_call_policies
>
struct with_custodian_and_ward : BasePolicy_
{
static PyObject* precall(PyObject* args);
BOOST_STATIC_ASSERT(custodian != ward);
BOOST_STATIC_ASSERT(custodian > 0);
BOOST_STATIC_ASSERT(ward > 0);
template <class ArgumentPackage>
static bool precall(ArgumentPackage const& args_)
{
unsigned arity_ = detail::arity(args_);
if (custodian > arity_ || ward > arity_)
{
PyErr_SetString(
PyExc_IndexError
, "boost::python::with_custodian_and_ward: argument index out of range"
);
return false;
}
# if 0 // argpkg
PyObject* patient = detail::get(mpl::int_<(ward-1)>(), args_);
PyObject* nurse = detail::get(mpl::int_<(custodian-1)>(), args_);
# else
PyObject* patient = detail::get<(ward-1)>(args_);
PyObject* nurse = detail::get<(custodian-1)>(args_);
# endif
PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient);
if (life_support == 0)
return false;
bool result = BasePolicy_::precall(args_);
if (!result)
Py_DECREF(life_support);
return result;
}
};
template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies>
struct with_custodian_and_ward_postcall : BasePolicy_
{
static PyObject* postcall(PyObject* args, PyObject* result);
BOOST_STATIC_ASSERT(custodian != ward);
template <class ArgumentPackage>
static PyObject* postcall(ArgumentPackage const& args_, PyObject* result)
{
unsigned arity_ = detail::arity(args_);
if ( custodian > arity_ || ward > arity_ )
{
PyErr_SetString(
PyExc_IndexError
, "boost::python::with_custodian_and_ward_postcall: argument index out of range"
);
return 0;
}
# if 0 // argpkg
PyObject* patient = ward > 0 ? detail::get(mpl::int_<(ward-1)>(),args_) : result;
PyObject* nurse = custodian > 0 ? detail::get(mpl::int_<(custodian-1)>(),args_) : result;
# else
PyObject* patient = ward > 0 ? detail::get<(ward-1)>(args_) : result;
PyObject* nurse = custodian > 0 ? detail::get<(custodian-1)>(args_) : result;
# endif
if (nurse == 0) return 0;
result = BasePolicy_::postcall(args_, result);
if (result == 0)
return 0;
if (python::objects::make_nurse_and_patient(nurse, patient) == 0)
{
Py_XDECREF(result);
return 0;
}
return result;
}
};
//
// implementations
//
template <std::size_t custodian, std::size_t ward, class BasePolicy_>
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 0;
PyObject* nurse = PyTuple_GetItem(args_, custodian - 1);
if (nurse == 0)
return 0;
PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient);
if (life_support == 0)
return 0;
args_ = BasePolicy_::precall(args_);
if (args_ == 0)
Py_XDECREF(life_support);
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)
{
BOOST_STATIC_ASSERT(custodian != ward);
PyObject* patient = ward > 0 ? PyTuple_GetItem(args_, ward - 1) : result;
if (patient == 0) return 0;
PyObject* nurse = custodian > 0 ? PyTuple_GetItem(args_, custodian - 1) : result;
if (nurse == 0) return 0;
result = BasePolicy_::postcall(args_, result);
if (result == 0)
return 0;
if (python::objects::make_nurse_and_patient(nurse, patient) == 0)
{
Py_XDECREF(result);
return 0;
}
return result;
}
}} // namespace boost::python

View File

@@ -67,6 +67,7 @@ bpl-test crossmod_exception
: crossmod_exception.py crossmod_exception_a.cpp crossmod_exception_b.cpp
;
bpl-test injected ;
bpl-test properties ;
bpl-test return_arg ;
bpl-test staticmethod ;

35
test/injected.cpp Executable file
View File

@@ -0,0 +1,35 @@
// Copyright David Abrahams 2003. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include "test_class.hpp"
#include <memory>
#include <boost/shared_ptr.hpp>
#include <boost/python/make_constructor.hpp>
using namespace boost::python;
typedef test_class<> X;
X* empty() { return new X(1000); }
std::auto_ptr<X> sum(int a, int b) { return std::auto_ptr<X>(new X(a+b)); }
boost::shared_ptr<X> product(int a, int b, int c)
{
return boost::shared_ptr<X>(new X(a*b*c));
}
BOOST_PYTHON_MODULE(injected_ext)
{
class_<X>("X", init<int>())
.def("__init__", make_constructor(empty))
.def("__init__", make_constructor(sum))
.def("__init__", make_constructor(product))
.def("value", &X::value)
;
}

25
test/injected.py Normal file
View File

@@ -0,0 +1,25 @@
'''
>>> from injected_ext import *
>>> X(3,5).value() - (3+5)
0
>>> X(3,5,7).value() - (3*5*7)
0
>>> X().value()
1000
'''
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
status = run()[0]
if (status == 0): print "Done."
sys.exit(status)