diff --git a/include/boost/python/data_members.hpp b/include/boost/python/data_members.hpp index 58efb3d2..e5ff7082 100644 --- a/include/boost/python/data_members.hpp +++ b/include/boost/python/data_members.hpp @@ -20,20 +20,40 @@ # include # include -# include # include # include -# include +# include # include # include +# include # include +# include + namespace boost { namespace python { +// +// This file defines the make_getter and make_setter function +// families, which are responsible for turning pointers, references, +// and pointers-to-data-members into callable Python objects which +// can be used for attribute access on wrapped classes. +// + namespace detail { + // + // Raw Getter and Setter function generators. These class templates + // generate static functions which can be bound together with + // policies and wrapped to generate the python callable objects + // mentioned above. + // + + // + // Generates get and set functions for access through + // pointers-to-data-members + // template struct member { @@ -74,6 +94,12 @@ namespace detail } }; + // + // Generates get and set functions for access through ordinary + // pointers. These are generally used to wrap static data members, + // but can also be used to expose namespace-scope data as class + // attributes. + // template struct datum { @@ -108,6 +134,17 @@ namespace detail } }; + // + // Helper metafunction for determining the default CallPolicy to use + // for attribute access. If T is a [reference to a] class type X + // whose conversion to python would normally produce a new copy of X + // in a wrapped X class instance (as opposed to types such as + // std::string, which are converted to native Python types, and + // smart pointer types which produce a wrapped class instance of the + // pointee type), to-python conversions will attempt to produce an + // object which refers to the original C++ object, rather than a + // copy. See default_member_getter_policy for rationale. + // template struct default_getter_by_ref : mpl::and_< @@ -123,6 +160,9 @@ namespace detail { }; + // Metafunction computing the default CallPolicy to use for reading + // data members + // // If it's a regular class type (not an object manager or other // type for which we have to_python specializations, use // return_internal_reference so that we can do things like @@ -130,82 +170,124 @@ namespace detail // and get the right result. template struct default_member_getter_policy - : mpl::if_< - default_getter_by_ref - , return_internal_reference<> - , return_value_policy - > + : mpl::if_< + default_getter_by_ref + , return_internal_reference<> + , return_value_policy + > {}; + // Metafunction computing the default CallPolicy to use for reading + // non-member data. template struct default_datum_getter_policy - : mpl::if_< - default_getter_by_ref - , return_value_policy - , return_value_policy - > + : mpl::if_< + default_getter_by_ref + , return_value_policy + , return_value_policy + > {}; + // + // make_getter helper function family -- These helpers to + // boost::python::make_getter are used to dispatch behavior. The + // third argument is a workaround for a CWPro8 partial ordering bug + // with pointers to data members. It should be convertible to + // mpl::true_ iff the first argument is a pointer-to-member, and + // mpl::false_ otherwise. The fourth argument is for compilers + // which don't support partial ordering at all and should always be + // passed 0L. + // + + // Handle non-member pointers with policies template - inline object make_getter(D* p, Policies const& policies, int) + inline object make_getter(D* d, Policies const& policies, mpl::false_, int) { return objects::function_object( + objects::py_function( ::boost::bind( - &detail::datum::get, p, _1, _2 + &detail::datum::get, d, _1, _2 , policies) - , 0); + , mpl::vector1() + ) + ); } - + + // Handle non-member pointers without policies template - inline object make_getter(D* p, not_specified, long) + inline object make_getter(D* d, not_specified, mpl::false_, long) { typedef typename default_datum_getter_policy::type policies; - return make_getter(p, policies(), 0L); + return detail::make_getter(d, policies(), mpl::false_(), 0); } + // Handle pointers-to-members with policies template - inline object make_getter(D C::*pm, Policies const& policies, int) + inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int) { return objects::function_object( + objects::py_function( ::boost::bind( &detail::member::get, pm, _1, _2 , policies) - , 1); + , mpl::vector2() + ) + ); } + // Handle pointers-to-members without policies template - inline object make_getter(D C::*pm, not_specified, long) + inline object make_getter(D C::*pm, not_specified, mpl::true_, long) { typedef typename default_member_getter_policy::type policies; - return make_getter(pm, policies(), 0L); - } - - template - inline object make_getter(D& d, Policies const& policies, ...) - { - return detail::make_getter(&d, policies, 0L); + return detail::make_getter(pm, policies(), mpl::true_(), 0); } + // Handle references + template + inline object make_getter(D& d, P& p, mpl::false_, ...) + { + // Just dispatch to the handler for pointer types. + return detail::make_getter(&d, p, mpl::false_(), 0L); + } + + // + // make_setter helper function family -- These helpers to + // boost::python::make_setter are used to dispatch behavior. The + // third argument is for compilers which don't support partial + // ordering at all and should always be passed 0. + // + + + // Handle non-member pointers template - inline object make_setter(D* p, Policies const& policies, long) + inline object make_setter(D* p, Policies const& policies, int) { return objects::function_object( - ::boost::bind( - &detail::datum::set, p, _1, _2 - , policies) - , 1); + objects::py_function( + ::boost::bind( + &detail::datum::set, p, _1, _2 + , policies) + , mpl::vector2() + ) + ); } + // Handle pointers-to-members template - inline object make_setter(D C::*pm, Policies const& policies, long) + inline object make_setter(D C::*pm, Policies const& policies, int) { return objects::function_object( - ::boost::bind( - &detail::member::set, pm, _1, _2 - , policies) - , 2); + objects::py_function( + ::boost::bind( + &detail::member::set, pm, _1, _2 + , policies) + , mpl::vector3() + ) + ); } + // Handle references template inline object make_setter(D& x, Policies const& policies, ...) { @@ -213,55 +295,71 @@ namespace detail } } +// +// make_getter function family -- build a callable object which +// retrieves data through the first argument and is appropriate for +// use as the `get' function in Python properties . The second, +// policies argument, is optional. We need both D& and D const& +// overloads in order be able to handle rvalues. +// template inline object make_getter(D& d, Policies const& policies) { - return detail::make_getter(d, policies, 0L); + return detail::make_getter(d, policies, is_member_pointer(), 0L); } template inline object make_getter(D const& d, Policies const& policies) { - return detail::make_getter(d, policies, 0L); + return detail::make_getter(d, policies, is_member_pointer(), 0L); } template inline object make_getter(D& x) { - return detail::make_getter(x, detail::not_specified(), 0L); + detail::not_specified policy; + return detail::make_getter(x, policy, is_member_pointer(), 0L); } -# if !(BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__EDG_VERSION__, <= 238)) +# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) template -inline object make_getter(D const& x) +inline object make_getter(D const& d) { - return detail::make_getter(x, detail::not_specified(), 0L); + detail::not_specified policy; + return detail::make_getter(d, policy, is_member_pointer(), 0L); } -# endif +# endif +// +// make_setter function family -- build a callable object which +// writes data through the first argument and is appropriate for +// use as the `set' function in Python properties . The second, +// policies argument, is optional. We need both D& and D const& +// overloads in order be able to handle rvalues. +// template inline object make_setter(D& x, Policies const& policies) { - return detail::make_setter(x, policies, 0L); + return detail::make_setter(x, policies, 0); } template inline object make_setter(D const& x, Policies const& policies) { - return detail::make_setter(x, policies, 0L); + return detail::make_setter(x, policies, 0); } template inline object make_setter(D& x) { - return detail::make_setter(x, default_call_policies(), 0L); + return detail::make_setter(x, default_call_policies(), 0); } # if !(BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__EDG_VERSION__, <= 238)) template inline object make_setter(D const& x) { - return detail::make_setter(x, default_call_policies(), 0L); + return detail::make_setter(x, default_call_policies(), 0); } # endif diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index 3477f64d..392c0bee 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -14,6 +14,7 @@ # include # include # include +# include # include # include @@ -25,7 +26,9 @@ # include # include +# include # include +# include namespace boost { namespace python { namespace detail { @@ -58,15 +61,18 @@ struct select_result_converter template struct caller_arity; +template +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; -# define BOOST_PYTHON_ARG_CONVERTER(n) \ - BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \ - BOOST_PYTHON_NEXT(ConverterGenerators, conv_iter,n) \ - typedef typename apply_iter1::type c_t##n; \ - c_t##n c##n(PyTuple_GET_ITEM(args_, n)); \ - if (!c##n.convertible()) \ +# define BOOST_PYTHON_ARG_CONVERTER(n) \ + BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \ + BOOST_PYTHON_NEXT(ConverterGenerators, conv_iter,n) \ + typedef typename apply_iter1::type c_t##n; \ + c_t##n c##n(PyTuple_GET_ITEM(args_, n)); \ + if (!c##n.convertible()) \ return 0; # define BOOST_PP_ITERATION_PARAMS_1 \ @@ -119,8 +125,8 @@ struct caller typedef PyObject* result_type; caller(F f, CallPolicies p) : base(f,p) {} -}; +}; }}} // namespace boost::python::detail @@ -163,6 +169,14 @@ struct caller_arity return m_data.second().postcall(args_, result); } + + static unsigned min_arity() { return N; } + + static char const*const* type_names() + { + return signature::type_names(); + } + private: compressed_pair m_data; }; diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 44d0e310..142f56c1 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -71,7 +71,7 @@ # define BOOST_PYTHON_NO_TEMPLATE_EXPORT #endif -#if defined(BOOST_PYTHON_DYNAMIC_LIB) && defined(_WIN32) || defined(__CYGWIN__) +#if defined(BOOST_PYTHON_DYNAMIC_LIB) && (defined(_WIN32) || defined(__CYGWIN__)) # if defined(BOOST_PYTHON_SOURCE) # define BOOST_PYTHON_DECL __declspec(dllexport) # define BOOST_PYTHON_BUILD_DLL diff --git a/include/boost/python/detail/defaults_gen.hpp b/include/boost/python/detail/defaults_gen.hpp index f1a367a4..4416bdda 100644 --- a/include/boost/python/detail/defaults_gen.hpp +++ b/include/boost/python/detail/defaults_gen.hpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace boost { namespace python { @@ -203,26 +204,26 @@ namespace detail }; \ }; -#define BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ - fstubs_name(char const* doc = 0) \ - : ::boost::python::detail::overloads_common(doc) {} \ - template \ - fstubs_name(char const* doc, Keywords const& keywords) \ - : ::boost::python::detail::overloads_common( \ - doc, keywords.range()) \ - { \ - typedef typename ::boost::python::detail:: \ - error::more_keywords_than_function_arguments< \ - Keywords::size,n_args>::too_many_keywords assertion; \ - } \ - template \ - fstubs_name(Keywords const& keywords, char const* doc = 0) \ - : ::boost::python::detail::overloads_common( \ - doc, keywords.range()) \ - { \ - typedef typename ::boost::python::detail:: \ - error::more_keywords_than_function_arguments< \ - Keywords::size,n_args>::too_many_keywords assertion; \ +#define BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ + fstubs_name(char const* doc = 0) \ + : ::boost::python::detail::overloads_common(doc) {} \ + template \ + fstubs_name(char const* doc, ::boost::python::detail::keywords const& keywords) \ + : ::boost::python::detail::overloads_common( \ + doc, keywords.range()) \ + { \ + typedef typename ::boost::python::detail:: \ + error::more_keywords_than_function_arguments< \ + N,n_args>::too_many_keywords assertion; \ + } \ + template \ + fstubs_name(::boost::python::detail::keywords const& keywords, char const* doc = 0) \ + : ::boost::python::detail::overloads_common( \ + doc, keywords.range()) \ + { \ + typedef typename ::boost::python::detail:: \ + error::more_keywords_than_function_arguments< \ + N,n_args>::too_many_keywords assertion; \ } # if defined(BOOST_NO_VOID_RETURNS) diff --git a/include/boost/python/detail/msvc_typeinfo.hpp b/include/boost/python/detail/msvc_typeinfo.hpp index 0139984b..2c9990fb 100644 --- a/include/boost/python/detail/msvc_typeinfo.hpp +++ b/include/boost/python/detail/msvc_typeinfo.hpp @@ -49,17 +49,24 @@ template< typename T > T&(* is_ref_tester1(type) )(type) { return 0; } inline char BOOST_TT_DECL is_ref_tester1(...) { return 0; } template -inline typeinfo msvc_typeid(boost::type* = 0) +inline typeinfo msvc_typeid(boost::type*) { return detail::typeid_ref( (boost::type*)0, detail::is_ref_tester1(type()) ); } +template <> +inline typeinfo msvc_typeid(boost::type*) +{ + return typeid(void); +} + # ifndef NDEBUG inline typeinfo assert_array_typeid_compiles() { - return msvc_typeid(), msvc_typeid(); + return msvc_typeid((boost::type*)0) + , msvc_typeid((boost::type*)0); } # endif diff --git a/include/boost/python/has_back_reference.hpp b/include/boost/python/has_back_reference.hpp index d27d8f4c..7d8a6500 100644 --- a/include/boost/python/has_back_reference.hpp +++ b/include/boost/python/has_back_reference.hpp @@ -7,6 +7,7 @@ # define HAS_BACK_REFERENCE_DWA2002323_HPP # include +# include namespace boost { namespace python { @@ -14,8 +15,8 @@ namespace boost { namespace python { // contains a back-reference to its owning PyObject* template struct has_back_reference + : mpl::false_ { - BOOST_STATIC_CONSTANT(bool, value = false); }; diff --git a/include/boost/python/init.hpp b/include/boost/python/init.hpp index 712f1e99..aea9d635 100644 --- a/include/boost/python/init.hpp +++ b/include/boost/python/init.hpp @@ -203,22 +203,22 @@ class init : public init_base > : base(doc_) { } - - template - init(char const* doc_, Keywords const& kw) - : base(doc_, std::make_pair(kw.base(), kw.base() + Keywords::size)) - { - typedef typename detail::error::more_keywords_than_init_arguments< - Keywords::size, n_arguments::value - >::too_many_keywords assertion; - } - template - init(Keywords const& kw, char const* doc_ = 0) + template + init(char const* doc_, detail::keywords const& kw) : base(doc_, kw.range()) { typedef typename detail::error::more_keywords_than_init_arguments< - Keywords::size, n_arguments::value + N, n_arguments::value + >::too_many_keywords assertion; + } + + template + init(detail::keywords const& kw, char const* doc_ = 0) + : base(doc_, kw.range()) + { + typedef typename detail::error::more_keywords_than_init_arguments< + N, n_arguments::value >::too_many_keywords assertion; } diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp index 818c7c6a..91db7c88 100644 --- a/include/boost/python/make_function.hpp +++ b/include/boost/python/make_function.hpp @@ -37,7 +37,7 @@ namespace detail { return objects::function_object( detail::caller(f, p) - , mpl::size::value - 1); + ); } // As above, except that it accepts argument keywords. NumKeywords @@ -62,8 +62,7 @@ namespace detail return objects::function_object( detail::caller(f, p) - , arity - , kw); + , kw); } } diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index 34af05e4..20a76a2b 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -19,8 +19,6 @@ struct BOOST_PYTHON_DECL function : PyObject { function( py_function const& - , unsigned min_arity - , unsigned max_arity , python::detail::keyword const* names_and_defaults , unsigned num_keywords); @@ -48,8 +46,6 @@ struct BOOST_PYTHON_DECL function : PyObject private: // data members py_function m_fn; - unsigned m_min_arity; - unsigned m_max_arity; handle m_overloads; object m_name; object m_doc; diff --git a/include/boost/python/object/function_handle.hpp b/include/boost/python/object/function_handle.hpp index 29efa2be..67896336 100644 --- a/include/boost/python/object/function_handle.hpp +++ b/include/boost/python/object/function_handle.hpp @@ -14,7 +14,7 @@ namespace boost { namespace python { namespace objects { -BOOST_PYTHON_DECL handle<> function_handle_impl(py_function const& f, unsigned min_args, unsigned max_args = 0); +BOOST_PYTHON_DECL handle<> function_handle_impl(py_function const& f); // Just like function_object, but returns a handle<> instead. Using // this for arg_to_python<> allows us to break a circular dependency @@ -26,9 +26,11 @@ inline handle<> function_handle(F const& f, Signature) return objects::function_handle_impl( python::detail::caller< - F,python::detail::args_from_python,default_call_policies,Signature>( - f, default_call_policies()) - , n_arguments, n_arguments); + F,python::detail::args_from_python,default_call_policies,Signature + >( + f, default_call_policies() + ) + ); } // Just like make_function, but returns a handle<> intead. Same diff --git a/include/boost/python/object/function_object.hpp b/include/boost/python/object/function_object.hpp index 207d62b9..0bf91669 100644 --- a/include/boost/python/object/function_object.hpp +++ b/include/boost/python/object/function_object.hpp @@ -17,15 +17,13 @@ namespace objects { BOOST_PYTHON_DECL api::object function_object( py_function const& f - , unsigned min_arity, unsigned max_arity , python::detail::keyword_range const&); BOOST_PYTHON_DECL api::object function_object( py_function const& f - , unsigned arity , python::detail::keyword_range const&); - BOOST_PYTHON_DECL api::object function_object(py_function const& f, unsigned arity); + BOOST_PYTHON_DECL api::object function_object(py_function const& f); // Add an attribute to the name_space with the given name. If it is // a Boost.Python function object diff --git a/include/boost/python/object/iterator.hpp b/include/boost/python/object/iterator.hpp index c97c3994..af7f68aa 100644 --- a/include/boost/python/object/iterator.hpp +++ b/include/boost/python/object/iterator.hpp @@ -16,12 +16,15 @@ # include # include # include +# include # include # include # include # include # include +# include + namespace boost { namespace python { namespace objects { // CallPolicies for the next() method of iterators. We don't want @@ -118,8 +121,18 @@ namespace detail // Make a callable object which can be used as the iterator's next() function. object next_function = objects::function_object( + py_function( bind(&detail::iterator_next::execute, _1, _2, policies) - , 1); + , mpl::vector2< +# if defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + object +# else + typename boost::detail::iterator_traits::value_type +# endif + , Iterator + >() + ) + ); return class_(name, no_init) .def("__iter__", identity_function()) @@ -164,16 +177,25 @@ namespace detail template inline object make_iterator_function( - Accessor1 const& get_start, Accessor2 const& get_finish, Iterator const& (*)(), boost::type*, NextPolicies*, int) + Accessor1 const& get_start + , Accessor2 const& get_finish + , Iterator const& (*)() + , boost::type* + , NextPolicies* + , int + ) { return objects::function_object( - boost::bind( - &make_iterator_help< - Target,Iterator,Accessor1,Accessor2,NextPolicies - >::create - , get_start, get_finish, _1, _2) - , 1 ); + py_function( + boost::bind( + &make_iterator_help< + Target,Iterator,Accessor1,Accessor2,NextPolicies + >::create + , get_start, get_finish, _1, _2) + , mpl::vector2() + ) + ); } template diff --git a/include/boost/python/object/py_function.hpp b/include/boost/python/object/py_function.hpp index 0682d692..610f5b30 100644 --- a/include/boost/python/object/py_function.hpp +++ b/include/boost/python/object/py_function.hpp @@ -5,7 +5,11 @@ // to its suitability for any purpose. #ifndef PY_FUNCTION_DWA200286_HPP # define PY_FUNCTION_DWA200286_HPP -# include + +# include +# include +# include +# include namespace boost { namespace python { namespace objects { @@ -13,9 +17,142 @@ namespace boost { namespace python { namespace objects { // function signature: // // PyObject* (PyObject* args, PyObject* keywords) -// -// We use boost::function to avoid generating lots of virtual tables -typedef boost::function2 py_function; + +struct BOOST_PYTHON_DECL py_function_impl_base +{ + virtual ~py_function_impl_base(); + virtual PyObject* operator()(PyObject*, PyObject*) = 0; + virtual unsigned min_arity() const = 0; + virtual unsigned max_arity() const; + virtual char const* const* type_names() const = 0; +}; + +template +struct caller_py_function_impl : py_function_impl_base +{ + caller_py_function_impl(Caller const& caller) + : m_caller(caller) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) + { + return m_caller(args, kw); + } + + virtual unsigned min_arity() const + { + return m_caller.min_arity(); + } + + virtual char const* const* type_names() const + { + return m_caller.type_names(); + } + + private: + Caller m_caller; +}; + +template +struct signature_py_function_impl : py_function_impl_base +{ + signature_py_function_impl(Caller const& caller) + : m_caller(caller) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) + { + return m_caller(args, kw); + } + + virtual unsigned min_arity() const + { + return mpl::size::value - 1; + } + + virtual char const* const* type_names() const + { + return python::detail::signature::type_names(); + } + + private: + Caller m_caller; +}; + +template +struct full_py_function_impl : py_function_impl_base +{ + full_py_function_impl(Caller const& caller, unsigned min_arity, unsigned max_arity) + : m_caller(caller) + , m_min_arity(min_arity) + , m_max_arity(max_arity > min_arity ? max_arity : min_arity) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) + { + return m_caller(args, kw); + } + + virtual unsigned min_arity() const + { + return m_min_arity; + } + + virtual unsigned max_arity() const + { + return m_max_arity; + } + + virtual char const* const* type_names() const + { + return python::detail::signature::type_names(); + } + + private: + Caller m_caller; + unsigned m_min_arity; + unsigned m_max_arity; +}; + +struct py_function +{ + template + py_function(Caller const& caller) + : m_impl(new caller_py_function_impl(caller)) + {} + + template + py_function(Caller const& caller, Sig) + : m_impl(new signature_py_function_impl(caller)) + {} + + template + py_function(Caller const& caller, Sig, int min_arity, int max_arity = 0) + : m_impl(new full_py_function_impl(caller, min_arity, max_arity)) + {} + + py_function(py_function const& rhs) + : m_impl(rhs.m_impl) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) const + { + return (*m_impl)(args, kw); + } + + unsigned min_arity() const + { + return m_impl->min_arity(); + } + + unsigned max_arity() const + { + return m_impl->max_arity(); + } + + private: + mutable std::auto_ptr m_impl; +}; }}} // namespace boost::python::objects diff --git a/include/boost/python/object/select_holder.hpp b/include/boost/python/object/select_holder.hpp index 87bc06da..00636a95 100644 --- a/include/boost/python/object/select_holder.hpp +++ b/include/boost/python/object/select_holder.hpp @@ -21,6 +21,7 @@ # include # include # include +# include # include # include @@ -49,7 +50,7 @@ namespace detail // constructor. Normally this means U is a virtual function // dispatcher subclass for T. template - void check_default_constructible(T*, U*, mpl::bool_) + void check_default_constructible(T*, U*, mpl::true_) { python::detail::force_instantiate( sizeof(specify_init_arguments_or_no_init_for_class_(U((::PyObject*)0))) @@ -59,7 +60,7 @@ namespace detail // Handles the "normal" case where T is held directly and // has_back_reference is not specialized. template - void check_default_constructible(T*, T*, mpl::bool_) + void check_default_constructible(T*, T*, mpl::false_) { python::detail::force_instantiate( sizeof(specify_init_arguments_or_no_init_for_class_(T())) @@ -90,17 +91,22 @@ namespace detail template struct select_value_holder { - BOOST_STATIC_CONSTANT(bool, back_ref = (!is_same::value) | has_back_reference::value); - + private: + typedef mpl::or_< + mpl::not_ > + , has_back_reference + > use_back_ref; + + public: static void assert_default_constructible() { - detail::check_default_constructible((T*)0,(Held*)0,mpl::bool_()); + detail::check_default_constructible((T*)0,(Held*)0, use_back_ref()); } - typedef typename mpl::if_c< - back_ref - , value_holder_back_reference - , value_holder + typedef typename mpl::if_< + use_back_ref + , value_holder_back_reference + , value_holder >::type type; static inline void register_() {} @@ -111,23 +117,28 @@ namespace detail template struct select_pointer_holder { - typedef typename python::pointee::type pointee; - BOOST_STATIC_CONSTANT(bool, back_ref = (!is_same::value) | has_back_reference::value); - + private: + typedef typename python::pointee::type wrapper; + typedef mpl::or_< + mpl::not_ > + , has_back_reference + > use_back_ref; + + public: static void assert_default_constructible() { - detail::check_default_constructible((T*)0,(pointee*)0,mpl::bool_()); + detail::check_default_constructible((T*)0,(wrapper*)0, use_back_ref()); } - typedef typename mpl::if_c< - back_ref + typedef typename mpl::if_< + use_back_ref , pointer_holder_back_reference , pointer_holder >::type type; static inline void register_() { - select_pointer_holder::register_(mpl::bool_()); + select_pointer_holder::register_(use_back_ref()); } static type* get() { return 0; } diff --git a/include/boost/python/opaque_pointer_converter.hpp b/include/boost/python/opaque_pointer_converter.hpp index 6f025c87..8f9a1dd9 100644 --- a/include/boost/python/opaque_pointer_converter.hpp +++ b/include/boost/python/opaque_pointer_converter.hpp @@ -113,22 +113,24 @@ PyTypeObject opaque_pointer_converter::type_object = ::boost::python::detail::dealloc }; }} // namespace boost::python -# ifdef BOOST_MSVC +# ifdef BOOST_MSVC // MSC works without this workaround, but needs another one ... -# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ -BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee) -# else -# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ -namespace boost { namespace python { \ - template<> \ - inline type_info type_id(boost::type*) { \ - return type_info (typeid (Pointee *)); \ - } \ - template<> \ - inline type_info type_id( \ - boost::type*) { \ - return type_info (typeid (Pointee *)); \ - } \ +# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ + BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee) +# else +# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ + namespace boost { namespace python { \ + template<> \ + inline type_info type_id(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee)) \ + { \ + return type_info (typeid (Pointee *)); \ + } \ + template<> \ + inline type_info type_id( \ + BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&)) \ + { \ + return type_info (typeid (Pointee *)); \ + } \ }} -# endif +# endif # endif // OPAQUE_POINTER_CONVERTER_HPP_ diff --git a/include/boost/python/raw_function.hpp b/include/boost/python/raw_function.hpp index e33c0ac5..db861e12 100755 --- a/include/boost/python/raw_function.hpp +++ b/include/boost/python/raw_function.hpp @@ -11,7 +11,9 @@ # include # include # include +# include +# include # include namespace boost { namespace python { @@ -31,17 +33,25 @@ namespace detail ).ptr() ); } + private: F f; }; - object BOOST_PYTHON_DECL make_raw_function(objects::py_function, std::size_t min_args); + object BOOST_PYTHON_DECL make_raw_function(objects::py_function); } template object raw_function(F f, std::size_t min_args = 0) { - return detail::make_raw_function(detail::raw_dispatcher(f), min_args); + return detail::make_raw_function( + objects::py_function( + detail::raw_dispatcher(f) + , mpl::vector1() + , min_args + , std::numeric_limits::max() + ) + ); } }} // namespace boost::python diff --git a/include/boost/python/type_id.hpp b/include/boost/python/type_id.hpp index 908e0ac1..96ca44da 100755 --- a/include/boost/python/type_id.hpp +++ b/include/boost/python/type_id.hpp @@ -57,14 +57,20 @@ struct type_info : private totally_ordered base_id_t m_base_type; }; +# ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# define BOOST_PYTHON_EXPLICIT_TT_DEF(T) ::boost::type* +# else +# define BOOST_PYTHON_EXPLICIT_TT_DEF(T) +# endif + template -inline type_info type_id(boost::type* = 0) +inline type_info type_id(BOOST_EXPLICIT_TEMPLATE_TYPE(T)) { return type_info( # if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 700) typeid(T) # else // strip the decoration which msvc and Intel mistakenly leave in - python::detail::msvc_typeid() + python::detail::msvc_typeid((boost::type*)0) # endif ); } @@ -76,11 +82,11 @@ inline type_info type_id(boost::type* = 0) // down into template instantiations. Explicit specialization stops // that from taking hold. -# define BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(T) \ -template <> \ -inline type_info type_id(boost::type*) \ -{ \ - return type_info(typeid(T)); \ +# define BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(T) \ +template <> \ +inline type_info type_id(BOOST_PYTHON_EXPLICIT_TT_DEF(T)) \ +{ \ + return type_info(typeid(T)); \ } BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(short) diff --git a/src/object/function.cpp b/src/object/function.cpp index 761a9866..d9f333a8 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -14,33 +14,42 @@ #include #include +#include +#include + +#include + #include #include namespace boost { namespace python { namespace objects { +py_function_impl_base::~py_function_impl_base() +{ +} + +unsigned py_function_impl_base::max_arity() const +{ + return this->min_arity(); +} + extern PyTypeObject function_type; function::function( py_function const& implementation - , unsigned min_arity - , unsigned max_arity , python::detail::keyword const* names_and_defaults , unsigned num_keywords ) : m_fn(implementation) - , m_min_arity(min_arity) - // was using std::max here, but a problem with MinGW-2.95 and - // our directory prevents it. - , m_max_arity(max_arity > min_arity ? max_arity : min_arity) { if (names_and_defaults != 0) { - unsigned keyword_offset - = m_max_arity > num_keywords ? m_max_arity - num_keywords : 0; + unsigned int max_arity = m_fn.max_arity(); + unsigned int keyword_offset + = max_arity > num_keywords ? max_arity - num_keywords : 0; - unsigned tuple_size = num_keywords ? m_max_arity : 0; + unsigned tuple_size = num_keywords ? max_arity : 0; m_arg_names = object(handle<>(PyTuple_New(tuple_size))); if (num_keywords != 0) @@ -86,7 +95,8 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const do { // Check for a plausible number of arguments - if (total_args >= f->m_min_arity && total_args <= f->m_max_arity) + if (total_args >= f->m_fn.min_arity() + && total_args <= f->m_fn.max_arity()) { // This will be the args that actually get passed handle<> args2(allow_null(borrowed(args))); @@ -242,7 +252,7 @@ namespace } // Something for the end of the chain of binary operators - PyObject* not_implemented_impl(PyObject*, PyObject*) + PyObject* not_implemented(PyObject*, PyObject*) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -250,9 +260,11 @@ namespace handle not_implemented_function() { + static object keeper( - function_object(¬_implemented_impl, 2, 3 - , python::detail::keyword_range()) + function_object( + py_function(¬_implemented, mpl::vector1(), 2) + , python::detail::keyword_range()) ); return handle(borrowed(downcast(keeper.ptr()))); } @@ -478,48 +490,38 @@ PyTypeObject function_type = { }; object function_object( - py_function const& f, unsigned min_arity, unsigned max_arity + py_function const& f , python::detail::keyword_range const& keywords) { return python::object( python::detail::new_non_null_reference( new function( - f, min_arity, max_arity, keywords.first, keywords.second - keywords.first))); + f, keywords.first, keywords.second - keywords.first))); } -object function_object( - py_function const& f - , unsigned arity - , python::detail::keyword_range const& kw) +object function_object(py_function const& f) { - return function_object(f, arity, arity, kw); -} - -object function_object(py_function const& f, unsigned arity) -{ - return function_object(f, arity, arity, python::detail::keyword_range()); + return function_object(f, python::detail::keyword_range()); } -handle<> function_handle_impl(py_function const& f, unsigned min_arity, unsigned max_arity) +handle<> function_handle_impl(py_function const& f) { return python::handle<>( allow_null( - new function(f, min_arity, max_arity, 0, 0))); + new function(f, 0, 0))); } } namespace detail { - object BOOST_PYTHON_DECL make_raw_function(objects::py_function f, std::size_t min_args) + object BOOST_PYTHON_DECL make_raw_function(objects::py_function f) { static keyword k; return objects::function_object( f - , min_args - , std::numeric_limits::max() , keyword_range(&k,&k)); } } diff --git a/src/object/iterator.cpp b/src/object/iterator.cpp index 1718ee59..bfde2680 100644 --- a/src/object/iterator.cpp +++ b/src/object/iterator.cpp @@ -7,19 +7,27 @@ #include #include #include +#include namespace boost { namespace python { namespace objects { -static PyObject* identity(PyObject* args_, PyObject*) +namespace { - PyObject* x = PyTuple_GET_ITEM(args_,0); - Py_INCREF(x); - return x; + PyObject* identity(PyObject* args_, PyObject*) + { + PyObject* x = PyTuple_GET_ITEM(args_,0); + Py_INCREF(x); + return x; + } } BOOST_PYTHON_DECL object const& identity_function() { - static object result(function_object(&identity, 1)); + static object result( + function_object( + py_function(&identity, mpl::vector2()) + ) + ); return result; } diff --git a/test/Jamfile b/test/Jamfile index 1354dc09..854dc3f4 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -61,6 +61,7 @@ run ../test/embedding.cpp ../build/boost_python : # requirements $(PYTHON_PROPERTIES) BOOST_PYTHON_STATIC_LIB + BOOST_PYTHON_STATIC_MODULE $(PYTHON_LIB_PATH) <$(gcc-compilers)>$(CYGWIN_PYTHON_DEBUG_DLL_PATH) <$(gcc-compilers)><*>$(CYGWIN_PYTHON_DLL_PATH) @@ -151,9 +152,9 @@ run indirect_traits_test.cpp ; run destroy_test.cpp ; run pointer_type_id_test.cpp ../../test/build/boost_test_exec_monitor : : : $(UNIT_TEST_PROPERTIES) ; run member_function_cast.cpp ; -run bases.cpp ; +run bases.cpp : : : $(UNIT_TEST_PROPERTIES) ; run if_else.cpp ; -run pointee.cpp ; +run pointee.cpp : : : $(UNIT_TEST_PROPERTIES) ; run result.cpp ; compile string_literal.cpp ; diff --git a/test/back_reference.cpp b/test/back_reference.cpp index 75233c6b..f2545f57 100644 --- a/test/back_reference.cpp +++ b/test/back_reference.cpp @@ -14,6 +14,7 @@ #include #include #include +#include // This test shows that a class can be wrapped "as itself" but also // acquire a back-reference iff has_back_reference<> is appropriately @@ -64,14 +65,14 @@ namespace boost { namespace python { template <> struct has_back_reference + : mpl::true_ { - BOOST_STATIC_CONSTANT(bool, value = true); }; template <> struct has_back_reference + : mpl::true_ { - BOOST_STATIC_CONSTANT(bool, value = true); }; }} diff --git a/test/input_iterator.cpp b/test/input_iterator.cpp index eacae455..e4021e83 100644 --- a/test/input_iterator.cpp +++ b/test/input_iterator.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include using namespace boost::python; @@ -21,7 +21,7 @@ struct doubler int operator()(int x) const { return x * 2; } }; -typedef boost::transform_iterator_generator::type doubling_iterator; +typedef boost::transform_iterator doubling_iterator; typedef std::pair list_range2; list_range2 range2(list_int& x) diff --git a/test/opaque.py b/test/opaque.py index 55afa11f..a8073669 100644 --- a/test/opaque.py +++ b/test/opaque.py @@ -1,8 +1,10 @@ +# -*- coding: iso-latin-1 -*- # Copyright Gottfried Ganßauge 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. + """ >>> from opaque_ext import * >>> # diff --git a/test/select_holder.cpp b/test/select_holder.cpp index 0bf5ac15..93d57f11 100644 --- a/test/select_holder.cpp +++ b/test/select_holder.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #define BOOST_INCLUDE_MAIN @@ -24,8 +25,8 @@ namespace boost { namespace python // specialization template <> struct has_back_reference
+ : mpl::true_ { - BOOST_STATIC_CONSTANT(bool, value = true); }; }} // namespace boost::python diff --git a/test/str.cpp b/test/str.cpp index e0252a17..9e675208 100644 --- a/test/str.cpp +++ b/test/str.cpp @@ -38,7 +38,7 @@ void work_with_string(object print) str tabstr("\t\ttab\tdemo\t!"); print(tabstr.expandtabs()); print(tabstr.expandtabs(4)); - print(tabstr.expandtabs(7.9)); + print(tabstr.expandtabs(7L)); print("operators"); print( str("part1") + str("part2") );