Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:37

0001 #if !defined(BOOST_PP_IS_ITERATING)
0002 
0003 // Copyright David Abrahams 2002.
0004 // Distributed under the Boost Software License, Version 1.0. (See
0005 // accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 # ifndef CALLER_DWA20021121_HPP
0009 #  define CALLER_DWA20021121_HPP
0010 
0011 #  include <boost/python/type_id.hpp>
0012 #  include <boost/python/handle.hpp>
0013 
0014 #  include <boost/detail/indirect_traits.hpp>
0015 
0016 #  include <boost/python/detail/invoke.hpp>
0017 #  include <boost/python/detail/signature.hpp>
0018 #  include <boost/python/detail/preprocessor.hpp>
0019 #  include <boost/python/detail/type_traits.hpp>
0020 
0021 #  include <boost/python/arg_from_python.hpp>
0022 #  include <boost/python/converter/context_result_converter.hpp>
0023 #  include <boost/python/converter/builtin_converters.hpp>
0024 
0025 #  include <boost/preprocessor/iterate.hpp>
0026 #  include <boost/preprocessor/cat.hpp>
0027 #  include <boost/preprocessor/dec.hpp>
0028 #  include <boost/preprocessor/if.hpp>
0029 #  include <boost/preprocessor/iteration/local.hpp>
0030 #  include <boost/preprocessor/repetition/enum_trailing_params.hpp>
0031 #  include <boost/preprocessor/repetition/repeat.hpp>
0032 
0033 #  include <boost/compressed_pair.hpp>
0034 
0035 #  include <boost/mpl/apply.hpp>
0036 #  include <boost/mpl/eval_if.hpp>
0037 #  include <boost/mpl/identity.hpp>
0038 #  include <boost/mpl/size.hpp>
0039 #  include <boost/mpl/at.hpp>
0040 #  include <boost/mpl/int.hpp>
0041 #  include <boost/mpl/next.hpp>
0042 
0043 namespace boost { namespace python { namespace detail { 
0044 
0045 template <int N>
0046 inline PyObject* get(mpl::int_<N>, PyObject* const& args_)
0047 {
0048     return PyTuple_GET_ITEM(args_,N);
0049 }
0050 
0051 inline Py_ssize_t arity(PyObject* const& args_)
0052 {
0053     return PyTuple_GET_SIZE(args_);
0054 }
0055 
0056 // This "result converter" is really just used as
0057 // a dispatch tag to invoke(...), selecting the appropriate
0058 // implementation
0059 typedef int void_result_to_python;
0060 
0061 // Given a model of CallPolicies and a C++ result type, this
0062 // metafunction selects the appropriate converter to use for
0063 // converting the result to python.
0064 template <class Policies, class Result>
0065 struct select_result_converter
0066   : mpl::eval_if<
0067         is_same<Result,void>
0068       , mpl::identity<void_result_to_python>
0069       , mpl::apply1<typename Policies::result_converter,Result>
0070     >
0071 {
0072 };
0073 
0074 template <class ArgPackage, class ResultConverter>
0075 inline ResultConverter create_result_converter(
0076     ArgPackage const& args_
0077   , ResultConverter*
0078   , converter::context_result_converter*
0079 )
0080 {
0081     return ResultConverter(args_);
0082 }
0083     
0084 template <class ArgPackage, class ResultConverter>
0085 inline ResultConverter create_result_converter(
0086     ArgPackage const&
0087   , ResultConverter*
0088   , ...
0089 )
0090 {
0091     return ResultConverter();
0092 }
0093 
0094 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
0095 template <class ResultConverter>
0096 struct converter_target_type 
0097 {
0098     static PyTypeObject const *get_pytype()
0099     {
0100         return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype();
0101     }
0102 };
0103 
0104 template < >
0105 struct converter_target_type <void_result_to_python >
0106 {
0107     static PyTypeObject const *get_pytype()
0108     {
0109         return 0;
0110     }
0111 };
0112 
0113 // Generation of ret moved from caller_arity<N>::impl::signature to here due to "feature" in MSVC 15.7.2 with /O2
0114 // which left the ret uninitialized and caused segfaults in Python interpreter.
0115 template<class Policies, class Sig> const signature_element* get_ret()
0116 {
0117     typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type<Sig>::type rtype;
0118     typedef typename select_result_converter<Policies, rtype>::type result_converter;
0119 
0120     static const signature_element ret = {
0121         (is_void<rtype>::value ? "void" : type_id<rtype>().name())
0122         , &detail::converter_target_type<result_converter>::get_pytype
0123         , boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value 
0124     };
0125 
0126     return &ret;
0127 }
0128 
0129 #endif
0130 
0131     
0132 template <unsigned> struct caller_arity;
0133 
0134 template <class F, class CallPolicies, class Sig>
0135 struct caller;
0136 
0137 #  define BOOST_PYTHON_NEXT(init,name,n)                                                        \
0138     typedef BOOST_PP_IF(n,typename mpl::next< BOOST_PP_CAT(name,BOOST_PP_DEC(n)) >::type, init) name##n;
0139 
0140 #  define BOOST_PYTHON_ARG_CONVERTER(n)                                         \
0141      BOOST_PYTHON_NEXT(typename mpl::next<first>::type, arg_iter,n)             \
0142      typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n;  \
0143      c_t##n c##n(get(mpl::int_<n>(), inner_args));                              \
0144      if (!c##n.convertible())                                                   \
0145           return 0;
0146 
0147 #  define BOOST_PP_ITERATION_PARAMS_1                                            \
0148         (3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/caller.hpp>))
0149 #  include BOOST_PP_ITERATE()
0150 
0151 #  undef BOOST_PYTHON_ARG_CONVERTER
0152 #  undef BOOST_PYTHON_NEXT
0153 
0154 // A metafunction returning the base class used for caller<class F,
0155 // class ConverterGenerators, class CallPolicies, class Sig>.
0156 template <class F, class CallPolicies, class Sig>
0157 struct caller_base_select
0158 {
0159     enum { arity = mpl::size<Sig>::value - 1 };
0160     typedef typename caller_arity<arity>::template impl<F,CallPolicies,Sig> type;
0161 };
0162 
0163 // A function object type which wraps C++ objects as Python callable
0164 // objects.
0165 //
0166 // Template Arguments:
0167 //
0168 //   F -
0169 //      the C++ `function object' that will be called. Might
0170 //      actually be any data for which an appropriate invoke_tag() can
0171 //      be generated. invoke(...) takes care of the actual invocation syntax.
0172 //
0173 //   CallPolicies -
0174 //      The precall, postcall, and what kind of resultconverter to
0175 //      generate for mpl::front<Sig>::type
0176 //
0177 //   Sig -
0178 //      The `intended signature' of the function. An MPL sequence
0179 //      beginning with a result type and continuing with a list of
0180 //      argument types.
0181 template <class F, class CallPolicies, class Sig>
0182 struct caller
0183     : caller_base_select<F,CallPolicies,Sig>::type
0184 {
0185     typedef typename caller_base_select<
0186         F,CallPolicies,Sig
0187         >::type base;
0188 
0189     typedef PyObject* result_type;
0190     
0191     caller(F f, CallPolicies p) : base(f,p) {}
0192 
0193 };
0194 
0195 }}} // namespace boost::python::detail
0196 
0197 # endif // CALLER_DWA20021121_HPP
0198 
0199 #else
0200 
0201 # define N BOOST_PP_ITERATION()
0202 
0203 template <>
0204 struct caller_arity<N>
0205 {
0206     template <class F, class Policies, class Sig>
0207     struct impl
0208     {
0209         impl(F f, Policies p) : m_data(f,p) {}
0210 
0211         PyObject* operator()(PyObject* args_, PyObject*) // eliminate
0212                                                          // this
0213                                                          // trailing
0214                                                          // keyword dict
0215         {
0216             typedef typename mpl::begin<Sig>::type first;
0217             typedef typename first::type result_t;
0218             typedef typename select_result_converter<Policies, result_t>::type result_converter;
0219             typedef typename Policies::argument_package argument_package;
0220             
0221             argument_package inner_args(args_);
0222 
0223 # if N
0224 #  define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i)
0225 #  define BOOST_PP_LOCAL_LIMITS (0, N-1)
0226 #  include BOOST_PP_LOCAL_ITERATE()
0227 # endif 
0228             // all converters have been checked. Now we can do the
0229             // precall part of the policy
0230             if (!m_data.second().precall(inner_args))
0231                 return 0;
0232 
0233             PyObject* result = detail::invoke(
0234                 detail::invoke_tag<result_t,F>()
0235               , create_result_converter(args_, (result_converter*)0, (result_converter*)0)
0236               , m_data.first()
0237                 BOOST_PP_ENUM_TRAILING_PARAMS(N, c)
0238             );
0239             
0240             return m_data.second().postcall(inner_args, result);
0241         }
0242 
0243         static unsigned min_arity() { return N; }
0244         
0245         static py_func_sig_info  signature()
0246         {
0247             const signature_element * sig = detail::signature<Sig>::elements();
0248 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
0249             // MSVC 15.7.2, when compiling to /O2 left the static const signature_element ret, 
0250             // originally defined here, uninitialized. This in turn led to SegFault in Python interpreter.
0251             // Issue is resolved by moving the generation of ret to separate function in detail namespace (see above).
0252             const signature_element * ret = detail::get_ret<Policies, Sig>();
0253 
0254             py_func_sig_info res = {sig, ret };
0255 #else
0256             py_func_sig_info res = {sig, sig };
0257 #endif
0258 
0259             return  res;
0260         }
0261      private:
0262         compressed_pair<F,Policies> m_data;
0263     };
0264 };
0265 
0266 
0267 
0268 #endif // BOOST_PP_IS_ITERATING 
0269 
0270