1 // Copyright David Abrahams 2002. 2 // Distributed under the Boost Software License, Version 1.0. (See 3 // accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 #ifndef PY_FUNCTION_DWA200286_HPP 6 # define PY_FUNCTION_DWA200286_HPP 7 8 # include <boost/python/detail/signature.hpp> 9 # include <boost/detail/workaround.hpp> 10 # include <boost/mpl/size.hpp> 11 # include <memory> 12 13 namespace boost { namespace python { namespace objects { 14 15 // This type is used as a "generalized Python callback", wrapping the 16 // function signature: 17 // 18 // PyObject* (PyObject* args, PyObject* keywords) 19 20 struct BOOST_PYTHON_DECL py_function_impl_base 21 { 22 virtual ~py_function_impl_base(); 23 virtual PyObject* operator()(PyObject*, PyObject*) = 0; 24 virtual unsigned min_arity() const = 0; 25 virtual unsigned max_arity() const; 26 virtual python::detail::py_func_sig_info signature() const = 0; 27 }; 28 29 template <class Caller> 30 struct caller_py_function_impl : py_function_impl_base 31 { caller_py_function_implboost::python::objects::caller_py_function_impl32 caller_py_function_impl(Caller const& caller) 33 : m_caller(caller) 34 {} 35 operator ()boost::python::objects::caller_py_function_impl36 PyObject* operator()(PyObject* args, PyObject* kw) 37 { 38 return m_caller(args, kw); 39 } 40 min_arityboost::python::objects::caller_py_function_impl41 virtual unsigned min_arity() const 42 { 43 return m_caller.min_arity(); 44 } 45 signatureboost::python::objects::caller_py_function_impl46 virtual python::detail::py_func_sig_info signature() const 47 { 48 return m_caller.signature(); 49 } 50 51 private: 52 Caller m_caller; 53 }; 54 55 template <class Caller, class Sig> 56 struct signature_py_function_impl : py_function_impl_base 57 { signature_py_function_implboost::python::objects::signature_py_function_impl58 signature_py_function_impl(Caller const& caller) 59 : m_caller(caller) 60 {} 61 operator ()boost::python::objects::signature_py_function_impl62 PyObject* operator()(PyObject* args, PyObject* kw) 63 { 64 return m_caller(args, kw); 65 } 66 min_arityboost::python::objects::signature_py_function_impl67 virtual unsigned min_arity() const 68 { 69 return mpl::size<Sig>::value - 1; 70 } 71 signatureboost::python::objects::signature_py_function_impl72 virtual python::detail::py_func_sig_info signature() const 73 { 74 python::detail::signature_element const* sig = python::detail::signature<Sig>::elements(); 75 python::detail::py_func_sig_info res = {sig, sig}; 76 return res; 77 } 78 79 private: 80 Caller m_caller; 81 }; 82 83 template <class Caller, class Sig> 84 struct full_py_function_impl : py_function_impl_base 85 { full_py_function_implboost::python::objects::full_py_function_impl86 full_py_function_impl(Caller const& caller, unsigned min_arity, unsigned max_arity) 87 : m_caller(caller) 88 , m_min_arity(min_arity) 89 , m_max_arity(max_arity > min_arity ? max_arity : min_arity) 90 {} 91 operator ()boost::python::objects::full_py_function_impl92 PyObject* operator()(PyObject* args, PyObject* kw) 93 { 94 return m_caller(args, kw); 95 } 96 min_arityboost::python::objects::full_py_function_impl97 virtual unsigned min_arity() const 98 { 99 return m_min_arity; 100 } 101 max_arityboost::python::objects::full_py_function_impl102 virtual unsigned max_arity() const 103 { 104 return m_max_arity; 105 } 106 signatureboost::python::objects::full_py_function_impl107 virtual python::detail::py_func_sig_info signature() const 108 { 109 python::detail::signature_element const* sig = python::detail::signature<Sig>::elements(); 110 python::detail::py_func_sig_info res = {sig, sig}; 111 return res; 112 } 113 114 private: 115 Caller m_caller; 116 unsigned m_min_arity; 117 unsigned m_max_arity; 118 }; 119 120 struct py_function 121 { 122 template <class Caller> py_functionboost::python::objects::py_function123 py_function(Caller const& caller) 124 : m_impl(new caller_py_function_impl<Caller>(caller)) 125 {} 126 127 template <class Caller, class Sig> py_functionboost::python::objects::py_function128 py_function(Caller const& caller, Sig) 129 : m_impl(new signature_py_function_impl<Caller, Sig>(caller)) 130 {} 131 132 template <class Caller, class Sig> py_functionboost::python::objects::py_function133 py_function(Caller const& caller, Sig, int min_arity, int max_arity = 0) 134 : m_impl(new full_py_function_impl<Caller, Sig>(caller, min_arity, max_arity)) 135 {} 136 py_functionboost::python::objects::py_function137 py_function(py_function const& rhs) 138 #if defined(BOOST_NO_CXX11_SMART_PTR) 139 : m_impl(rhs.m_impl) 140 #else 141 : m_impl(std::move(rhs.m_impl)) 142 #endif 143 {} 144 operator ()boost::python::objects::py_function145 PyObject* operator()(PyObject* args, PyObject* kw) const 146 { 147 return (*m_impl)(args, kw); 148 } 149 min_arityboost::python::objects::py_function150 unsigned min_arity() const 151 { 152 return m_impl->min_arity(); 153 } 154 max_arityboost::python::objects::py_function155 unsigned max_arity() const 156 { 157 return m_impl->max_arity(); 158 } 159 signatureboost::python::objects::py_function160 python::detail::signature_element const* signature() const 161 { 162 return m_impl->signature().signature; 163 } 164 get_return_typeboost::python::objects::py_function165 python::detail::signature_element const& get_return_type() const 166 { 167 return *m_impl->signature().ret; 168 } 169 170 private: 171 #if defined(BOOST_NO_CXX11_SMART_PTR) 172 mutable std::auto_ptr<py_function_impl_base> m_impl; 173 #else 174 mutable std::unique_ptr<py_function_impl_base> m_impl; 175 #endif 176 }; 177 178 }}} // namespace boost::python::objects 179 180 #endif // PY_FUNCTION_DWA200286_HPP 181