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:
18
include/boost/python/converter/context_result_converter.hpp
Executable file
18
include/boost/python/converter/context_result_converter.hpp
Executable 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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
283
include/boost/python/make_constructor.hpp
Executable file
283
include/boost/python/make_constructor.hpp
Executable 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
35
test/injected.cpp
Executable 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
25
test/injected.py
Normal 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)
|
||||
|
||||
Reference in New Issue
Block a user