123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- #if !defined(BOOST_PP_IS_ITERATING)
- // Copyright David Abrahams 2002.
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- # ifndef CALLER_DWA20021121_HPP
- # define CALLER_DWA20021121_HPP
- # include <boost/python/type_id.hpp>
- # include <boost/python/handle.hpp>
- # include <boost/detail/indirect_traits.hpp>
- # include <boost/python/detail/invoke.hpp>
- # include <boost/python/detail/signature.hpp>
- # include <boost/python/detail/preprocessor.hpp>
- # include <boost/python/detail/type_traits.hpp>
- # include <boost/python/arg_from_python.hpp>
- # include <boost/python/converter/context_result_converter.hpp>
- # include <boost/python/converter/builtin_converters.hpp>
- # include <boost/preprocessor/iterate.hpp>
- # include <boost/preprocessor/cat.hpp>
- # include <boost/preprocessor/dec.hpp>
- # include <boost/preprocessor/if.hpp>
- # include <boost/preprocessor/iteration/local.hpp>
- # include <boost/preprocessor/repetition/enum_trailing_params.hpp>
- # include <boost/preprocessor/repetition/repeat.hpp>
- # include <boost/compressed_pair.hpp>
- # include <boost/mpl/apply.hpp>
- # include <boost/mpl/eval_if.hpp>
- # include <boost/mpl/identity.hpp>
- # include <boost/mpl/size.hpp>
- # include <boost/mpl/at.hpp>
- # include <boost/mpl/int.hpp>
- # include <boost/mpl/next.hpp>
- namespace boost { namespace python { namespace detail {
- template <int N>
- inline PyObject* get(mpl::int_<N>, PyObject* const& args_)
- {
- return PyTuple_GET_ITEM(args_,N);
- }
- inline Py_ssize_t 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
- typedef int void_result_to_python;
- // Given a model of CallPolicies and a C++ result type, this
- // metafunction selects the appropriate converter to use for
- // converting the result to python.
- template <class Policies, class Result>
- struct select_result_converter
- : mpl::eval_if<
- is_same<Result,void>
- , 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&
- , ResultConverter*
- , ...
- )
- {
- return ResultConverter();
- }
- #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
- template <class ResultConverter>
- struct converter_target_type
- {
- static PyTypeObject const *get_pytype()
- {
- return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype();
- }
- };
- template < >
- struct converter_target_type <void_result_to_python >
- {
- static PyTypeObject const *get_pytype()
- {
- return 0;
- }
- };
- // Generation of ret moved from caller_arity<N>::impl::signature to here due to "feature" in MSVC 15.7.2 with /O2
- // which left the ret uninitialized and caused segfaults in Python interpreter.
- template<class Policies, class Sig> const signature_element* get_ret()
- {
- typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type<Sig>::type rtype;
- typedef typename select_result_converter<Policies, rtype>::type result_converter;
- static const signature_element ret = {
- (is_void<rtype>::value ? "void" : type_id<rtype>().name())
- , &detail::converter_target_type<result_converter>::get_pytype
- , boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value
- };
- return &ret;
- }
- #endif
-
- template <unsigned> struct caller_arity;
- template <class F, class CallPolicies, class Sig>
- struct caller;
- # define BOOST_PYTHON_NEXT(init,name,n) \
- typedef BOOST_PP_IF(n,typename mpl::next< BOOST_PP_CAT(name,BOOST_PP_DEC(n)) >::type, init) name##n;
- # define BOOST_PYTHON_ARG_CONVERTER(n) \
- BOOST_PYTHON_NEXT(typename mpl::next<first>::type, arg_iter,n) \
- typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \
- c_t##n c##n(get(mpl::int_<n>(), inner_args)); \
- if (!c##n.convertible()) \
- return 0;
- # define BOOST_PP_ITERATION_PARAMS_1 \
- (3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/caller.hpp>))
- # include BOOST_PP_ITERATE()
- # undef BOOST_PYTHON_ARG_CONVERTER
- # undef BOOST_PYTHON_NEXT
- // A metafunction returning the base class used for caller<class F,
- // class ConverterGenerators, class CallPolicies, class Sig>.
- template <class F, class CallPolicies, class Sig>
- struct caller_base_select
- {
- enum { arity = mpl::size<Sig>::value - 1 };
- typedef typename caller_arity<arity>::template impl<F,CallPolicies,Sig> type;
- };
- // A function object type which wraps C++ objects as Python callable
- // objects.
- //
- // Template Arguments:
- //
- // F -
- // the C++ `function object' that will be called. Might
- // actually be any data for which an appropriate invoke_tag() can
- // be generated. invoke(...) takes care of the actual invocation syntax.
- //
- // CallPolicies -
- // The precall, postcall, and what kind of resultconverter to
- // generate for mpl::front<Sig>::type
- //
- // Sig -
- // The `intended signature' of the function. An MPL sequence
- // beginning with a result type and continuing with a list of
- // argument types.
- template <class F, class CallPolicies, class Sig>
- struct caller
- : caller_base_select<F,CallPolicies,Sig>::type
- {
- typedef typename caller_base_select<
- F,CallPolicies,Sig
- >::type base;
- typedef PyObject* result_type;
-
- caller(F f, CallPolicies p) : base(f,p) {}
- };
- }}} // namespace boost::python::detail
- # endif // CALLER_DWA20021121_HPP
- #else
- # define N BOOST_PP_ITERATION()
- template <>
- struct caller_arity<N>
- {
- template <class F, class Policies, class Sig>
- struct impl
- {
- impl(F f, Policies p) : m_data(f,p) {}
- PyObject* operator()(PyObject* args_, PyObject*) // eliminate
- // this
- // trailing
- // keyword dict
- {
- 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)
- # include BOOST_PP_LOCAL_ITERATE()
- # endif
- // all converters have been checked. Now we can do the
- // precall part of the policy
- if (!m_data.second().precall(inner_args))
- return 0;
- PyObject* result = detail::invoke(
- 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);
- }
- static unsigned min_arity() { return N; }
-
- static py_func_sig_info signature()
- {
- const signature_element * sig = detail::signature<Sig>::elements();
- #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
- // MSVC 15.7.2, when compiling to /O2 left the static const signature_element ret,
- // originally defined here, uninitialized. This in turn led to SegFault in Python interpreter.
- // Issue is resolved by moving the generation of ret to separate function in detail namespace (see above).
- const signature_element * ret = detail::get_ret<Policies, Sig>();
- py_func_sig_info res = {sig, ret };
- #else
- py_func_sig_info res = {sig, sig };
- #endif
- return res;
- }
- private:
- compressed_pair<F,Policies> m_data;
- };
- };
- #endif // BOOST_PP_IS_ITERATING
|