diff --git a/include/boost/python/args.hpp b/include/boost/python/args.hpp new file mode 100644 index 00000000..dc00c96c --- /dev/null +++ b/include/boost/python/args.hpp @@ -0,0 +1,103 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. 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 ARGS_DWA2002323_HPP +# define ARGS_DWA2002323_HPP +# include + +# include + +# include + +# include +# include +# include + +namespace boost { namespace python { + +enum no_init_t { no_init }; + +namespace detail +{ + template + struct args_base {}; +} +}} + +# if !defined(__EDG_VERSION__) || __EDG_VERSION__ > 245 + +namespace boost { namespace python { + +// A type list for specifying arguments +template < BOOST_PYTHON_ENUM_WITH_DEFAULT(BOOST_PYTHON_MAX_ARITY, typename A, boost::mpl::null_argument) > +struct args : detail::args_base > + , boost::mpl::type_list< BOOST_PYTHON_UNARY_ENUM(BOOST_PYTHON_MAX_ARITY, A) >::type +{}; + +}} // namespace boost::python + +# else // slow template instantiators need this other version with + // explicit specializations of mpl::size<> and + // mpl::at<>. Eventually, however, inheritance from mpl::list + // *should* be eliminated and the two versions unified, just in + // order to get true arity independence + +namespace boost { namespace python { + +template < BOOST_PYTHON_ENUM_WITH_DEFAULT(BOOST_PYTHON_MAX_ARITY, typename A, boost::mpl::null_argument) > +struct args : detail::args_base > +{}; + +}} // namespace boost::python + +namespace boost { namespace mpl { + +template struct size; +template struct at; + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, , 1)) +# include BOOST_PP_ITERATE() + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY - 1, , 2)) +# include BOOST_PP_ITERATE() + + +}} // namespace boost::mpl + +# endif // __EDG_VERSION__ + +# endif // ARGS_DWA2002323_HPP + +/* ---------- size ---------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 +# line BOOST_PP_LINE(__LINE__, args.hpp(size)) + +# define N BOOST_PP_ITERATION() + +template +struct size > +{ + BOOST_STATIC_CONSTANT(long, value = N); +}; + +# undef N + +/* ---------- at ---------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2 +# line BOOST_PP_LINE(__LINE__, args.hpp(at)) + +# define N BOOST_PP_ITERATION() + +template +struct at > +{ + typedef BOOST_PP_CAT(A, N) type; +}; + +# undef N + +#endif diff --git a/include/boost/python/back_reference.hpp b/include/boost/python/back_reference.hpp new file mode 100644 index 00000000..75a14525 --- /dev/null +++ b/include/boost/python/back_reference.hpp @@ -0,0 +1,101 @@ +// Copyright David Abrahams 2002. 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 BACK_REFERENCE_DWA2002510_HPP +# define BACK_REFERENCE_DWA2002510_HPP + +# include +# include +# include + +namespace boost { namespace python { + +template +struct back_reference +{ + private: // types + typedef typename detail::dependent::type source_t; + public: + typedef T type; + + back_reference(PyObject*, T); + source_t const& source() const; + T get() const; + private: + source_t m_source; + T m_value; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +class is_back_reference +{ + public: + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +class is_back_reference > +{ + public: + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +# else // no partial specialization + +}} // namespace boost::python + +#include + +namespace boost { namespace python { + +namespace detail +{ + typedef char (&yes_back_reference_t)[1]; + typedef char (&no_back_reference_t)[2]; + + no_back_reference_t is_back_reference_test(...); + + template + yes_back_reference_t is_back_reference_test(boost::type< back_reference >); +} + +template +class is_back_reference +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_back_reference_test(boost::type())) + == sizeof(detail::yes_back_reference_t))); +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +// +// implementations +// +template +back_reference::back_reference(PyObject* p, T x) + : m_source(detail::borrowed_reference(p)) + , m_value(x) +{ +} + +template +typename back_reference::source_t const& back_reference::source() const +{ + return m_source; +} + +template +T back_reference::get() const +{ + return m_value; +} + +}} // namespace boost::python + +#endif // BACK_REFERENCE_DWA2002510_HPP diff --git a/include/boost/python/borrowed.hpp b/include/boost/python/borrowed.hpp new file mode 100755 index 00000000..10b1b5d1 --- /dev/null +++ b/include/boost/python/borrowed.hpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2002. 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 BORROWED_DWA2002614_HPP +# define BORROWED_DWA2002614_HPP +# include + +namespace boost { namespace python { + +template +inline python::detail::borrowed* borrowed(T* p) +{ + return (detail::borrowed*)p; +} + +}} // namespace boost::python + +#endif // BORROWED_DWA2002614_HPP diff --git a/include/boost/python/call.hpp b/include/boost/python/call.hpp new file mode 100644 index 00000000..6ce027ef --- /dev/null +++ b/include/boost/python/call.hpp @@ -0,0 +1,64 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. 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 CALL_DWA2002411_HPP +# define CALL_DWA2002411_HPP + +# include + +# include +# include +# include +# include + +# include +# include +# include +# include + +namespace boost { namespace python { + +# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \ + , converter::arg_to_python(a##n).get() + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET + +}} // namespace boost::python + +# endif // CALL_DWA2002411_HPP + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +# line BOOST_PP_LINE(__LINE__, call.hpp) + +# define N BOOST_PP_ITERATION() + +template < + class R + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_UNARY_ENUM(N, class A) + > +typename detail::returnable::type +call(PyObject* callable + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, const& a) + , boost::type* = 0 + ) +{ + converter::return_from_python converter; + return converter( + PyEval_CallFunction( + callable + , const_cast("(" BOOST_PP_REPEAT(N, BOOST_PYTHON_FIXED, "O") ")") + BOOST_PP_REPEAT(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) + )); +} + +# undef N + +#endif diff --git a/include/boost/python/call_method.hpp b/include/boost/python/call_method.hpp new file mode 100644 index 00000000..7c8f0e90 --- /dev/null +++ b/include/boost/python/call_method.hpp @@ -0,0 +1,64 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. 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 CALL_METHOD_DWA2002411_HPP +# define CALL_METHOD_DWA2002411_HPP + +# include + +# include +# include +# include +# include + +# include +# include +# include +# include + +namespace boost { namespace python { + +# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \ + , converter::arg_to_python(a##n).get() + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET + +}} // namespace boost::python + +# endif // CALL_METHOD_DWA2002411_HPP + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +# line BOOST_PP_LINE(__LINE__, call_method.hpp) + +# define N BOOST_PP_ITERATION() + +template < + class R + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_UNARY_ENUM(N, class A) + > +typename detail::returnable::type +call_method(PyObject* self, char const* name + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, const& a) + , boost::type* = 0 + ) +{ + converter::return_from_python converter; + return converter( + PyEval_CallMethod( + self + , const_cast(name) + , const_cast("(" BOOST_PP_REPEAT(N, BOOST_PYTHON_FIXED, "O") ")") + BOOST_PP_REPEAT(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) + )); +} + +# undef N + +#endif // BOOST_PP_IS_ITERATING diff --git a/include/boost/python/cast.hpp b/include/boost/python/cast.hpp new file mode 100755 index 00000000..d20cbd3a --- /dev/null +++ b/include/boost/python/cast.hpp @@ -0,0 +1,106 @@ +// Copyright David Abrahams 2002. 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 CAST_DWA200269_HPP +# define CAST_DWA200269_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template inline Target* upcast_impl(Source*, Target*); + + template + inline Target* upcast(Source* p, yes_convertible, no_convertible, Target*) + { + return p; + } + + template + inline Target* upcast(Source* p, no_convertible, no_convertible, Target*) + { + typedef typename base_type_traits::type base; + + return detail::upcast_impl((base*)p, (Target*)0); + } + + template + struct upcaster + { + template + static inline T* execute(T* x, T*) { return x; } + }; + + template <> + struct upcaster + { + template + static inline Target* execute(Source* x, Target*) + { + return detail::upcast( + x, detail::convertible::check(x) + , detail::convertible::check((Target*)0) + , (Target*)0); + } + }; + + + template + inline Target* downcast(Source* p, yes_convertible) + { + return static_cast(p); + } + + template + inline Target* downcast(Source* p, no_convertible, boost::type* = 0) + { + typedef typename base_type_traits::type base; + return (Target*)detail::downcast(p, convertible::check((base*)0)); + } + + template + inline void assert_castable(boost::type* = 0) + { + typedef char must_be_a_complete_type[sizeof(T)]; + } + + template + inline Target* upcast_impl(Source* x, Target*) + { + typedef typename add_cv::type src_t; + typedef typename add_cv::type target_t; + static bool const same = is_same::value; + + return detail::upcaster::execute(x, (Target*)0); + } +} + +template +inline Target* upcast(Source* x, Target* = 0) +{ + detail::assert_castable(); + detail::assert_castable(); + return detail::upcast_impl(x, (Target*)0); + +} + +template +inline Target* downcast(Source* x, Target* = 0) +{ + detail::assert_castable(); + detail::assert_castable(); + return detail::downcast(x, detail::convertible::check((Target*)0)); +} + +}} // namespace boost::python + +#endif // CAST_DWA200269_HPP diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp new file mode 100644 index 00000000..918cf4d2 --- /dev/null +++ b/include/boost/python/class.hpp @@ -0,0 +1,495 @@ +// Copyright David Abrahams 2002. 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 CLASS_DWA200216_HPP +# define CLASS_DWA200216_HPP + +# include +# include +# include +# include + +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + struct write_type_id; + + template + struct select_held_type; + + template + struct has_noncopyable; + + template + struct operator_; + + // Register a to_python converter for a class T, depending on the + // type of the first (tag) argument. The 2nd argument is a pointer + // to the type of holder that must be created. The 3rd argument is a + // reference to the Python type object to be created. + template + static inline void register_copy_constructor(mpl::bool_t const&, SelectHolder const& , T* = 0) + { + typedef typename SelectHolder::type holder; + force_instantiate(objects::class_wrapper >()); + SelectHolder::register_(); + } + + // Tag dispatched to have no effect. + template + static inline void register_copy_constructor(mpl::bool_t const&, SelectHolder const&, T* = 0) + { + SelectHolder::register_(); + } + + template int assert_default_constructible(T const&); +} + +// +// class_ +// +// This is the primary mechanism through which users will expose +// C++ classes to Python. The three template arguments are: +// +template < + class T // class being wrapped + , class X1 // = detail::not_specified + , class X2 // = detail::not_specified + , class X3 // = detail::not_specified + > +class class_ : public objects::class_base +{ + private: // types + typedef objects::class_base base; + + typedef class_ self; + BOOST_STATIC_CONSTANT(bool, is_copyable = (!detail::has_noncopyable::value)); + + typedef typename detail::select_held_type< + X1, typename detail::select_held_type< + X2, typename detail::select_held_type< + X3 + >::type>::type>::type held_type; + + typedef objects::select_holder holder_selector; + + typedef typename detail::select_bases::type + >::type + >::type bases; + + // A helper class which will contain an array of id objects to be + // passed to the base class constructor + struct id_vector + { + id_vector() + { + // Stick the derived class id into the first element of the array + ids[0] = type_id(); + + // Write the rest of the elements into succeeding positions. + type_info* p = ids + 1; + mpl::for_each::execute(&p); + } + + BOOST_STATIC_CONSTANT( + std::size_t, size = mpl::size::value + 1); + type_info ids[size]; + }; + friend struct id_vector; + + public: + // Automatically derive the class name - only works on some + // compilers because type_info::name is sometimes mangled (gcc) + class_(); // With default-constructor init function + class_(no_init_t); // With no init function + + // Construct with the class name, with or without docstring, and default init() function + class_(char const* name, char const* doc = 0); + + // Construct with class name, no docstring, and no init() function + class_(char const* name, no_init_t); + + // Construct with class name, docstring, and no init() function + class_(char const* name, char const* doc, no_init_t); + + template + inline class_(char const* name, detail::args_base const&) + : base(name, id_vector::size, id_vector().ids) + { + this->register_(); + this->def_init(InitArgs()); + this->set_instance_size(holder_selector::additional_size()); + } + + + template + inline class_(char const* name, char const* doc, detail::args_base const&, char const* initdoc = 0) + : base(name, id_vector::size, id_vector().ids, doc) + { + this->register_(); + this->def_init(InitArgs(), initdoc); + this->set_instance_size(holder_selector::additional_size()); + } + + // Wrap a member function or a non-member function which can take + // a T, T cv&, or T cv* as its first parameter, or a callable + // python object. + template + self& def(char const* name, F f) + { + this->def_impl(name, f, default_call_policies(), 0, &f); + return *this; + } + + template + self& def(init const& i) + { + define_init(*this, i, default_call_policies(), 0); + return *this; + } + + template + self& def( + init const& i, + CallPolicyOrDoc const& policy_or_doc, + char const* doc = 0) + { + typedef detail::def_helper helper; + define_init(*this, i, + helper::get_policy(policy_or_doc), + helper::get_doc(policy_or_doc, doc)); + return *this; + } + + template + self& def(char const* name, Arg1T arg1, Arg2T const& arg2) + { + // The arguments may be: + // arg1: function or signature + // arg2: policy or docstring or stubs + + dispatch_def(&arg2, name, arg1, arg2, (char*)0); + return *this; + } + + template + self& def(char const* name, Arg1T arg1, Arg2T const& arg2, Arg3T const& arg3) + { + // The arguments may be: + // arg1: function or signature + // arg2: policy or docstring or stubs + // arg3: policy or docstring + + dispatch_def(&arg2, name, arg1, arg2, arg3); + return *this; + } + + template + self& def(char const* name, Arg1T arg1, Arg2T const& arg2, Arg3T const& arg3, char const* doc) + { + // The arguments are definitely: + // arg1: signature + // arg2: stubs + // arg3: policy + + dispatch_def(&arg2, name, arg1, arg2, arg3, doc); + return *this; + } + + template + self& def(detail::operator_ const& op) + { + typedef detail::operator_ op_t; + return this->def(op.name(), &op_t::template apply::execute); + } + + // Define the constructor with the given Args, which should be an + // MPL sequence of types. + template + self& def_init(Args const&) + { + return this->def("__init__", + python::make_constructor( + // Using runtime type selection works around a CWPro7 bug. + holder_selector::execute((held_type*)0).get() + ) + ); + } + + template + self& def_init(Args const&, CallPolicyOrDoc const& policy_or_doc, char const* doc = 0) + { + typedef detail::def_helper helper; + + return this->def( + "__init__", + python::make_constructor( + helper::get_policy(policy_or_doc) + // Using runtime type selection works around a CWPro7 bug. + , holder_selector::execute((held_type*)0).get() + ) + , helper::get_doc(policy_or_doc, doc) + ); + } + + // Define the default constructor. + self& def_init() + { + this->def_init(mpl::type_list<>::type()); + return *this; + } + + // + // Data member access + // + template + self& def_readonly(char const* name, D T::*pm) + { + this->add_property(name, make_getter(pm)); + return *this; + } + + template + self& def_readwrite(char const* name, D T::*pm) + { + return this->add_property(name, make_getter(pm), make_setter(pm)); + } + + // Property creation + template + self& add_property(char const* name, Get const& fget) + { + base::add_property(name, object(fget)); + return *this; + } + + template + self& add_property(char const* name, Get const& fget, Set const& fset) + { + base::add_property(name, object(fget), object(fset)); + return *this; + } + + template + self& setattr(char const* name, U const& x) + { + this->base::setattr(name, object(x)); + return *this; + } + + // Pickle support + template + self& def_pickle(PickleSuiteType const& x) + { + error_messages::must_be_derived_from_pickle_suite(x); + detail::pickle_suite_finalize::register_( + *this, + &PickleSuiteType::getinitargs, + &PickleSuiteType::getstate, + &PickleSuiteType::setstate, + PickleSuiteType::getstate_manages_dict()); + return *this; + } + + private: // helper functions + + template + inline void def_impl(char const* name, Fn fn, Policies const& policies + , char const* doc, ...) + { + objects::add_to_namespace( + *this, name, + make_function( + // This bit of nastiness casts F to a member function of T if possible. + detail::member_function_cast::stage1(fn).stage2((T*)0).stage3(fn) + , policies) + , doc); + } + + template + inline void def_impl(char const* name, F f, default_call_policies const& + , char const* doc, object const*) + { + objects::add_to_namespace(*this, name, f, doc); + } + + inline void register_() const; + + template + void dispatch_def( + void const*, + char const* name, + Fn fn, + CallPolicyOrDoc const& policy_or_doc, + char const* doc) + { + typedef detail::def_helper helper; + + this->def_impl( + name, fn, helper::get_policy(policy_or_doc), + helper::get_doc(policy_or_doc, doc), &fn); + + } + + template + void dispatch_def( + detail::func_stubs_base const*, + char const* name, + SigT sig, + StubsT const& stubs, + CallPolicyOrDoc const& policy_or_doc, + char const* doc = 0) + { + typedef detail::def_helper helper; + + // convert sig to a type_list (see detail::get_signature in signature.hpp) + // before calling detail::define_with_defaults. + detail::define_with_defaults( + name, stubs, helper::get_policy(policy_or_doc), + *this, detail::get_signature(sig), + helper::get_doc(policy_or_doc, doc)); + } +}; + + +// +// implementations +// + // register converters +template +inline void class_::register_() const +{ + objects::register_class_from_python(); + + detail::register_copy_constructor( + mpl::bool_t() + , holder_selector::execute((held_type*)0) + ); +} + + + +template +inline class_::class_() + : base(typeid(T).name(), id_vector::size, id_vector().ids) +{ + this->register_(); + detail::force_instantiate(sizeof(detail::assert_default_constructible(T()))); + this->def_init(); + this->set_instance_size(holder_selector::additional_size()); +} + +template +inline class_::class_(no_init_t) + : base(typeid(T).name(), id_vector::size, id_vector().ids) +{ + this->register_(); + this->def_no_init(); +} + +template +inline class_::class_(char const* name, char const* doc) + : base(name, id_vector::size, id_vector().ids, doc) +{ + this->register_(); + detail::force_instantiate(sizeof(detail::assert_default_constructible(T()))); + this->def_init(); + this->set_instance_size(holder_selector::additional_size()); +} + +template +inline class_::class_(char const* name, no_init_t) + : base(name, id_vector::size, id_vector().ids) +{ + this->register_(); + this->def_no_init(); +} + +template +inline class_::class_(char const* name, char const* doc, no_init_t) + : base(name, id_vector::size, id_vector().ids, doc) +{ + this->register_(); + this->def_no_init(); +} + +namespace detail +{ + // This is an mpl BinaryMetaFunction object with a runtime behavior, + // which is to write the id of the type which is passed as its 2nd + // compile-time argument into the iterator pointed to by its runtime + // argument + struct write_type_id + { + // The first argument is Ignored because mpl::for_each is still + // currently an accumulate (reduce) implementation. + template struct apply + { + // also an artifact of accumulate-based for_each + typedef void type; + + // Here's the runtime behavior + static void execute(type_info** p) + { + *(*p)++ = type_id(); + } + }; + }; + + + template + struct has_noncopyable + : type_traits::ice_or< + is_same::value + , is_same::value + , is_same::value> + {}; + + + template + struct select_held_type + : mpl::select_type< + type_traits::ice_or< + specifies_bases::value + , is_same::value + >::value + , Prev + , T + > + { + }; +} + +}} // namespace boost::python + +#endif // CLASS_DWA200216_HPP diff --git a/include/boost/python/converter/arg_from_python.hpp b/include/boost/python/converter/arg_from_python.hpp new file mode 100755 index 00000000..585a30eb --- /dev/null +++ b/include/boost/python/converter/arg_from_python.hpp @@ -0,0 +1,336 @@ +// Copyright David Abrahams 2002. 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 ARG_FROM_PYTHON_DWA2002127_HPP +# define ARG_FROM_PYTHON_DWA2002127_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python +{ + template struct arg_from_python; +}} + +// This header defines Python->C++ function argument converters, +// parametrized on the argument type. + +namespace boost { namespace python { namespace converter { + +// +// lvalue converters +// +// These require that an lvalue of the type U is stored somewhere in +// the Python object being converted. + +// Used when T == U*const& +template +struct pointer_cref_arg_from_python +{ + typedef T result_type; + + pointer_cref_arg_from_python(PyObject*); + T operator()(PyObject*) const; + bool convertible() const; + + private: // storage for a U* + // needed because not all compilers will let us declare U* as the + // return type of operator() -- we return U*const& instead + typename python::detail::referent_storage::type m_result; +}; + +// Base class for pointer and reference converters +struct arg_lvalue_from_python_base +{ + public: // member functions + arg_lvalue_from_python_base(void* result); + bool convertible() const; + + protected: // member functions + void*const& result() const; + + private: // data members + void* m_result; +}; + +// Used when T == U* +template +struct pointer_arg_from_python : arg_lvalue_from_python_base +{ + typedef T result_type; + + pointer_arg_from_python(PyObject*); + T operator()(PyObject*) const; +}; + +// Used when T == U& and (T != V const& or T == W volatile&) +template +struct reference_arg_from_python : arg_lvalue_from_python_base +{ + typedef T result_type; + + reference_arg_from_python(PyObject*); + T operator()(PyObject*) const; +}; + +// =================== + +// +// rvalue converters +// +// These require only that an object of type T can be created from +// the given Python object, but not that the T object exist +// somewhere in storage. +// + +// Used when T is a plain value (non-pointer, non-reference) type or +// a (non-volatile) const reference to a plain value type. +template +struct arg_rvalue_from_python +{ + typedef typename boost::add_reference< + typename boost::add_const::type + >::type result_type; + + arg_rvalue_from_python(PyObject*); + bool convertible() const; + + result_type operator()(PyObject*); + + private: + rvalue_from_python_data m_data; +}; + + +// ================== + +// Converts to a (PyObject*,T) bundle, for when you need a reference +// back to the Python object +template +struct back_reference_arg_from_python + : boost::python::arg_from_python +{ + typedef T result_type; + + back_reference_arg_from_python(PyObject*); + T operator()(PyObject*); + private: + typedef boost::python::arg_from_python base; +}; + + +// ================== + +// This metafunction selects the appropriate arg_from_python converter +// type for an argument of type T. +template +struct select_arg_from_python +{ + BOOST_STATIC_CONSTANT( + bool, obj_mgr = is_object_manager::value); + + BOOST_STATIC_CONSTANT( + bool, obj_mgr_ref = is_reference_to_object_manager::value); + + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ptr_cref + = boost::python::detail::is_reference_to_pointer::value + && boost::python::detail::is_reference_to_const::value + && !boost::python::detail::is_reference_to_volatile::value); + + + BOOST_STATIC_CONSTANT( + bool, ref = + boost::python::detail::is_reference_to_non_const::value + || boost::python::detail::is_reference_to_volatile::value); + + BOOST_STATIC_CONSTANT( + bool, back_ref = + boost::python::is_back_reference::value); + + typedef typename mpl::select_type< + obj_mgr + , object_manager_value_arg_from_python + , typename mpl::select_type< + obj_mgr_ref + , object_manager_ref_arg_from_python + , typename mpl::select_type< + ptr + , pointer_arg_from_python + , typename mpl::select_type< + ptr_cref + , pointer_cref_arg_from_python + , typename mpl::select_type< + ref + , reference_arg_from_python + , typename mpl::select_type< + back_ref + , back_reference_arg_from_python + , arg_rvalue_from_python + >::type + >::type + >::type + >::type + >::type + >::type type; +}; + +// ================== + +// +// implementations +// + +// arg_lvalue_from_python_base +// +inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result) + : m_result(result) +{ +} + +inline bool arg_lvalue_from_python_base::convertible() const +{ + return m_result != 0; +} + +inline void*const& arg_lvalue_from_python_base::result() const +{ + return m_result; +} + +// pointer_cref_arg_from_python +// +namespace detail +{ + // null_ptr_reference -- a function returning a reference to a null + // pointer of type U. Needed so that extractors for T*const& can + // convert Python's None. + template + struct null_ptr_owner + { + static T value; + }; + template T null_ptr_owner::value = 0; + + template + inline U& null_ptr_reference(U&(*)()) + { + return null_ptr_owner::value; + } +} + +template +inline pointer_cref_arg_from_python::pointer_cref_arg_from_python(PyObject* p) +{ + // T == U*const&: store a U* in the m_result storage. Nonzero + // indicates success. If find returns nonzero, it's a pointer to + // a U object. + python::detail::write_void_ptr_reference( + m_result.bytes + , p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee::converters) + , (T(*)())0); +} + +template +inline bool pointer_cref_arg_from_python::convertible() const +{ + return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; +} +template +inline T pointer_cref_arg_from_python::operator()(PyObject* p) const +{ + return (p == Py_None) // None ==> 0 + ? detail::null_ptr_reference((T(*)())0) + // Otherwise, return a U*const& to the m_result storage. + : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); +} + +// pointer_arg_from_python +// +template +inline pointer_arg_from_python::pointer_arg_from_python(PyObject* p) + : arg_lvalue_from_python_base( + p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee::converters)) +{ +} + +template +inline T pointer_arg_from_python::operator()(PyObject* p) const +{ + return (p == Py_None) ? 0 : T(result()); +} + +// reference_arg_from_python +// +template +inline reference_arg_from_python::reference_arg_from_python(PyObject* p) + : arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered::converters)) +{ +} + +template +inline T reference_arg_from_python::operator()(PyObject*) const +{ + return python::detail::void_ptr_to_reference(result(), (T(*)())0); +} + + +// arg_rvalue_from_python +// +template +inline arg_rvalue_from_python::arg_rvalue_from_python(PyObject* obj) + : m_data(converter::rvalue_from_python_stage1(obj, registered::converters)) +{ +} + +template +inline bool arg_rvalue_from_python::convertible() const +{ + return m_data.stage1.convertible != 0; +} + +template +inline typename arg_rvalue_from_python::result_type +arg_rvalue_from_python::operator()(PyObject* p) +{ + if (m_data.stage1.construct != 0) + m_data.stage1.construct(p, &m_data.stage1); + + return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); +} + +// back_reference_arg_from_python +// +template +back_reference_arg_from_python::back_reference_arg_from_python(PyObject* x) + : base(x) +{ +} + +template +inline T +back_reference_arg_from_python::operator()(PyObject* x) +{ + return T(x, base::operator()(x)); +} + +}}} // namespace boost::python::converter + +#endif // ARG_FROM_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/arg_to_python.hpp b/include/boost/python/converter/arg_to_python.hpp new file mode 100755 index 00000000..7abb274c --- /dev/null +++ b/include/boost/python/converter/arg_to_python.hpp @@ -0,0 +1,247 @@ +// Copyright David Abrahams 2002. 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 ARG_TO_PYTHON_DWA200265_HPP +# define ARG_TO_PYTHON_DWA200265_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +// Bring in specializations +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct is_object_manager; + +namespace detail +{ + BOOST_PYTHON_DECL void throw_no_class_registered(); + + template + struct function_arg_to_python : handle<> + { + function_arg_to_python(T const& x); + }; + + template + struct reference_arg_to_python : handle<> + { + reference_arg_to_python(T& x); + private: + static PyObject* get_object(T& x); + }; + + template + struct value_arg_to_python : arg_to_python_base + { + // Throw an exception if the conversion can't succeed + value_arg_to_python(T const&); + }; + + template + struct pointer_deep_arg_to_python : arg_to_python_base + { + // Throw an exception if the conversion can't succeed + pointer_deep_arg_to_python(Ptr); + }; + + template + struct pointer_shallow_arg_to_python : handle<> + { + // Throw an exception if the conversion can't succeed + pointer_shallow_arg_to_python(Ptr); + private: + static PyObject* get_object(Ptr p); + }; + + // Convert types that manage a Python object to_python + template + struct object_manager_arg_to_python + { + object_manager_arg_to_python(T const& x) : m_src(x) {} + + PyObject* get() const + { + return python::upcast(get_managed_object(m_src, tag)); + } + + private: + T const& m_src; + }; + + template + struct select_arg_to_python + { + // Special handling for char const[N]; interpret them as char + // const* for the sake of conversion + BOOST_STATIC_CONSTANT( + bool, is_string = python::detail::is_string_literal::value); + + BOOST_STATIC_CONSTANT( + bool, function = is_function::value | python::detail::is_pointer_to_function::value | is_member_function_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, manager = is_object_manager::value); + + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ref_wrapper = is_reference_wrapper::value); + + BOOST_STATIC_CONSTANT( + bool, ptr_wrapper = is_pointer_wrapper::value); + + typedef typename unwrap_reference::type unwrapped_referent; + typedef typename unwrap_pointer::type unwrapped_ptr; + + typedef typename mpl::select_type< + is_string + , arg_to_python + , typename mpl::select_type< + function + , function_arg_to_python + , typename mpl::select_type< + manager + , object_manager_arg_to_python + , typename mpl::select_type< + ptr + , pointer_deep_arg_to_python + , typename mpl::select_type< + ptr_wrapper + , pointer_shallow_arg_to_python + , typename mpl::select_type< + ref_wrapper + , reference_arg_to_python + , value_arg_to_python + >::type + >::type + >::type + >::type + >::type + >::type + type; + }; +} + +template +struct arg_to_python + : detail::select_arg_to_python::type +{ + typedef typename detail::select_arg_to_python::type base; + public: // member functions + // Throw an exception if the conversion can't succeed + arg_to_python(T const& x); +}; + +// +// implementations +// +namespace detail +{ + // reject_raw_object_ptr -- cause a compile-time error if the user + // should pass a raw Python object pointer + using python::detail::yes_convertible; + using python::detail::no_convertible; + using python::detail::unspecialized; + + template struct cannot_convert_raw_PyObject; + + template + struct reject_raw_object_helper + { + static void error(Convertibility) + { + cannot_convert_raw_PyObject::to_python_use_handle_instead(); + } + static void error(...) {} + }; + + template + inline void reject_raw_object_ptr(T*) + { + reject_raw_object_helper::error( + python::detail::convertible::check((T*)0)); + + typedef typename remove_cv::type value_type; + + reject_raw_object_helper::error( + python::detail::convertible::check( + (base_type_traits*)0 + )); + } + // --------- + + template + inline function_arg_to_python::function_arg_to_python(T const& x) + : handle<>(python::objects::make_function_handle(x)) + { + } + + template + inline value_arg_to_python::value_arg_to_python(T const& x) + : arg_to_python_base(&x, registered::converters) + { + } + + template + inline pointer_deep_arg_to_python::pointer_deep_arg_to_python(Ptr x) + : arg_to_python_base(x, registered_pointee::converters) + { + detail::reject_raw_object_ptr((Ptr)0); + } + + template + inline PyObject* reference_arg_to_python::get_object(T& x) + { + to_python_indirect convert; + if (!convert.convertible()) + throw_no_class_registered(); + return convert(x); + } + + template + inline reference_arg_to_python::reference_arg_to_python(T& x) + : handle<>(reference_arg_to_python::get_object(x)) + { + } + + template + inline pointer_shallow_arg_to_python::pointer_shallow_arg_to_python(Ptr x) + : handle<>(pointer_shallow_arg_to_python::get_object(x)) + { + detail::reject_raw_object_ptr((Ptr)0); + } + + template + inline PyObject* pointer_shallow_arg_to_python::get_object(Ptr x) + { + to_python_indirect convert; + if (!convert.convertible()) + throw_no_class_registered(); + return x ? convert(x) : python::detail::none(); + } +} + +template +inline arg_to_python::arg_to_python(T const& x) + : base(x) +{} + +}}} // namespace boost::python::converter + +#endif // ARG_TO_PYTHON_DWA200265_HPP diff --git a/include/boost/python/converter/arg_to_python_base.hpp b/include/boost/python/converter/arg_to_python_base.hpp new file mode 100755 index 00000000..385a7839 --- /dev/null +++ b/include/boost/python/converter/arg_to_python_base.hpp @@ -0,0 +1,35 @@ +// Copyright David Abrahams 2002. 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 ARG_TO_PYTHON_BASE_DWA200237_HPP +# define ARG_TO_PYTHON_BASE_DWA200237_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct registration; + +namespace detail +{ + struct BOOST_PYTHON_DECL arg_to_python_base +# if !defined(BOOST_MSVC) || BOOST_MSVC <= 1300 || _MSC_FULL_VER > 13102179 + : handle<> +# endif + { + arg_to_python_base(void const volatile* source, registration const&); +# if defined(BOOST_MSVC) && BOOST_MSVC > 1300 && _MSC_FULL_VER <= 13102179 + PyObject* get() const { return m_ptr.get(); } + PyObject* release() { return m_ptr.release(); } + private: + handle<> m_ptr; +# endif + }; +} + +}}} // namespace boost::python::converter + +#endif // ARG_TO_PYTHON_BASE_DWA200237_HPP diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp new file mode 100644 index 00000000..aebfd459 --- /dev/null +++ b/include/boost/python/converter/builtin_converters.hpp @@ -0,0 +1,123 @@ +// Copyright David Abrahams 2002. 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 BUILTIN_CONVERTERS_DWA2002124_HPP +# define BUILTIN_CONVERTERS_DWA2002124_HPP +# include +# include +# include +# include +# include + +// Since all we can use to decide how to convert an object to_python +// is its C++ type, there can be only one such converter for each +// type. Therefore, for built-in conversions we can bypass registry +// lookups using explicit specializations of arg_to_python and +// result_to_python. + +namespace boost { namespace python { + +namespace converter +{ + template struct arg_to_python; + BOOST_PYTHON_DECL PyObject* do_return_to_python(char); + BOOST_PYTHON_DECL PyObject* do_return_to_python(char const*); + BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject*); + BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject*); +} + +// Provide specializations of to_python_value +template struct to_python_value; + +namespace detail +{ + // Since there's no registry lookup, always report the existence of + // a converter. + struct builtin_to_python + { + static bool convertible() { return true; } + }; +} + +// Use expr to create the PyObject corresponding to x +# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr) \ + template <> struct to_python_value \ + : detail::builtin_to_python \ + { \ + inline PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + }; \ + template <> struct to_python_value \ + : detail::builtin_to_python \ + { \ + inline PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + }; + +# define BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T, expr) \ + namespace converter \ + { \ + template <> struct arg_to_python< T > \ + : handle<> \ + { \ + arg_to_python(T const& x) \ + : python::handle<>(expr) {} \ + }; \ + } + +// Specialize argument and return value converters for T using expr +# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ + BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr) \ + BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr) + +// Specialize converters for signed and unsigned T to Python Int +# define BOOST_PYTHON_TO_INT(T) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, PyInt_FromLong(x)) + +// Bool is not signed. +BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, PyInt_FromLong(x)) + +// note: handles signed char and unsigned char, but not char (see below) +BOOST_PYTHON_TO_INT(char) + +BOOST_PYTHON_TO_INT(short) +BOOST_PYTHON_TO_INT(int) +BOOST_PYTHON_TO_INT(long) + +// using Python's macro instead of Boost's - we don't seem to get the +// config right all the time. +# ifdef HAVE_LONG_LONG +BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed LONG_LONG, PyLong_FromLongLong(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned LONG_LONG, PyLong_FromUnsignedLongLong(x)) +# endif + +# undef BOOST_TO_PYTHON_INT + +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x)) +BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag())) + +namespace converter +{ + + void initialize_builtin_converters(); + +} + +}} // namespace boost::python::converter + +#endif // BUILTIN_CONVERTERS_DWA2002124_HPP diff --git a/include/boost/python/converter/constructor_function.hpp b/include/boost/python/converter/constructor_function.hpp new file mode 100644 index 00000000..f3c49bd4 --- /dev/null +++ b/include/boost/python/converter/constructor_function.hpp @@ -0,0 +1,18 @@ +// Copyright David Abrahams 2002. 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 CONSTRUCTOR_FUNCTION_DWA200278_HPP +# define CONSTRUCTOR_FUNCTION_DWA200278_HPP + +namespace boost { namespace python { namespace converter { + +// Declares the type of functions used to construct C++ objects for +// rvalue from_python conversions. +struct rvalue_from_python_stage1_data; +typedef void (*constructor_function)(PyObject* source, rvalue_from_python_stage1_data*); + +}}} // namespace boost::python::converter + +#endif // CONSTRUCTOR_FUNCTION_DWA200278_HPP diff --git a/include/boost/python/converter/convertible_function.hpp b/include/boost/python/converter/convertible_function.hpp new file mode 100644 index 00000000..98db1cfb --- /dev/null +++ b/include/boost/python/converter/convertible_function.hpp @@ -0,0 +1,15 @@ +// Copyright David Abrahams 2002. 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 CONVERTIBLE_FUNCTION_DWA200278_HPP +# define CONVERTIBLE_FUNCTION_DWA200278_HPP + +namespace boost { namespace python { namespace converter { + +typedef void* (*convertible_function)(PyObject*); + +}}} // namespace boost::python::converter + +#endif // CONVERTIBLE_FUNCTION_DWA200278_HPP diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp new file mode 100644 index 00000000..dabafcaa --- /dev/null +++ b/include/boost/python/converter/from_python.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. 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 FIND_FROM_PYTHON_DWA2002223_HPP +# define FIND_FROM_PYTHON_DWA2002223_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct registration; +struct rvalue_from_python_chain; + +BOOST_PYTHON_DECL void* get_lvalue_from_python( + PyObject* source, registration const&); + +BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain( + PyObject* source, registration const&); + +BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( + PyObject* source, registration const&); + +BOOST_PYTHON_DECL void* rvalue_from_python_stage2( + PyObject* source, rvalue_from_python_stage1_data&, registration const&); + +BOOST_PYTHON_DECL void* rvalue_result_from_python( + PyObject*, rvalue_from_python_stage1_data&); + +BOOST_PYTHON_DECL void* reference_result_from_python(PyObject*, registration const&); +BOOST_PYTHON_DECL void* pointer_result_from_python(PyObject*, registration const&); + +BOOST_PYTHON_DECL void void_result_from_python(PyObject*); + +BOOST_PYTHON_DECL void throw_no_pointer_from_python(PyObject*, registration const&); +BOOST_PYTHON_DECL void throw_no_reference_from_python(PyObject*, registration const&); + +}}} // namespace boost::python::converter + +#endif // FIND_FROM_PYTHON_DWA2002223_HPP diff --git a/include/boost/python/converter/implicit.hpp b/include/boost/python/converter/implicit.hpp new file mode 100644 index 00000000..79a398aa --- /dev/null +++ b/include/boost/python/converter/implicit.hpp @@ -0,0 +1,57 @@ +// Copyright David Abrahams 2002. 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 IMPLICIT_DWA2002326_HPP +# define IMPLICIT_DWA2002326_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template +struct implicit +{ + static void* convertible(PyObject* obj) + { + // Find a converter chain which can produce a Source instance + // from obj. The user has told us that Source can be converted + // to Target, and instantiating construct() below, ensures + // that at compile-time. + return const_cast( + converter::implicit_conversion_chain(obj, registered::converters)); + } + + static void construct(PyObject* obj, rvalue_from_python_stage1_data* data) + { + // This is the chain we got from the convertible step + rvalue_from_python_chain const* chain + = static_cast(data->convertible); + + // Call the convertible function again + rvalue_from_python_data intermediate_data(chain->convertible(obj)); + + // Use the result to construct the source type if the first + // converter was an rvalue converter. + if (chain->construct != 0) + chain->construct(obj, &intermediate_data.stage1); + + void* storage = ((rvalue_from_python_storage*)data)->storage.bytes; +# if !defined(BOOST_MSVC) || _MSC_FULL_VER != 13012108 // vc7.01 alpha workaround + new (storage) Target(*static_cast(intermediate_data.stage1.convertible)); +# else + Target x(*static_cast(intermediate_data.stage1.convertible)); + new (storage) Target(x); +# endif + + // record successful construction + data->convertible = storage; + + } +}; + +}}} // namespace boost::python::converter + +#endif // IMPLICIT_DWA2002326_HPP diff --git a/include/boost/python/converter/obj_mgr_arg_from_python.hpp b/include/boost/python/converter/obj_mgr_arg_from_python.hpp new file mode 100644 index 00000000..75b0ae43 --- /dev/null +++ b/include/boost/python/converter/obj_mgr_arg_from_python.hpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2002. 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 OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP +# define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP + +# include +# include +# include +# include +# include +# include +# include + +// +// arg_from_python converters for Python type wrappers, to be used as +// base classes for specializations. +// +namespace boost { namespace python { namespace converter { + +template +struct object_manager_value_arg_from_python +{ + typedef T result_type; + + object_manager_value_arg_from_python(PyObject*); + bool convertible() const; + T operator()(PyObject*) const; + private: + PyObject* m_source; +}; + +// Used for converting reference-to-object-manager arguments from +// python. The process used here is a little bit odd. Upon +// construction, we build the object manager object in the m_result +// object, *forcing* it to accept the source Python object by casting +// its pointer to detail::borrowed_reference. This is supposed to +// bypass any type checking of the source object. The convertible +// check then extracts the owned object and checks it. If the check +// fails, nothing else in the program ever gets to touch this strange +// "forced" object. +template +struct object_manager_ref_arg_from_python +{ + typedef Ref result_type; + + object_manager_ref_arg_from_python(PyObject*); + bool convertible() const; + Ref operator()(PyObject*) const; + ~object_manager_ref_arg_from_python(); + private: + typename python::detail::referent_storage::type m_result; +}; + +// +// implementations +// + +template +inline object_manager_value_arg_from_python::object_manager_value_arg_from_python(PyObject* x) + : m_source(x) +{ +} + +template +inline bool object_manager_value_arg_from_python::convertible() const +{ + return object_manager_traits::check(m_source); +} + +template +inline T object_manager_value_arg_from_python::operator()(PyObject* x) const +{ + return T(python::detail::borrowed_reference(x)); +} + +template +inline object_manager_ref_arg_from_python::object_manager_ref_arg_from_python(PyObject* x) +{ + python::detail::construct_referent(&m_result.bytes, python::detail::borrowed_reference(x)); +} + +template +inline object_manager_ref_arg_from_python::~object_manager_ref_arg_from_python() +{ + python::detail::destroy_referent(this->m_result.bytes); +} + +namespace detail +{ + template + inline bool object_manager_ref_check(T const& x) + { + return object_manager_traits::check(get_managed_object(x, tag)); + } +} + +template +inline bool object_manager_ref_arg_from_python::convertible() const +{ + return detail::object_manager_ref_check( + python::detail::void_ptr_to_reference(this->m_result.bytes, (Ref(*)())0)); +} + +template +inline Ref object_manager_ref_arg_from_python::operator()(PyObject*) const +{ + return python::detail::void_ptr_to_reference( + this->m_result.bytes, (Ref(*)())0); +} + +}}} // namespace boost::python::converter + +#endif // OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP diff --git a/include/boost/python/converter/object_manager.hpp b/include/boost/python/converter/object_manager.hpp new file mode 100755 index 00000000..431ef708 --- /dev/null +++ b/include/boost/python/converter/object_manager.hpp @@ -0,0 +1,232 @@ +// Copyright David Abrahams 2002. 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 OBJECT_MANAGER_DWA2002614_HPP +# define OBJECT_MANAGER_DWA2002614_HPP + +# include +# include +# include +# include +# include +# include + +// Facilities for dealing with types which always manage Python +// objects. Some examples are object, list, str, et. al. Different +// to_python/from_python conversion rules apply here because in +// contrast to other types which are typically embedded inside a +// Python object, these are wrapped around a Python object. For most +// object managers T, a C++ non-const T reference argument does not +// imply the existence of a T lvalue embedded in the corresponding +// Python argument, since mutating member functions on T actually only +// modify the held Python object. +// +// handle is an object manager, though strictly speaking it should +// not be. In other words, even though mutating member functions of +// hanlde actually modify the handle and not the T object, +// handle& arguments of wrapped functions will bind to "rvalues" +// wrapping the actual Python argument, just as with other object +// manager classes. Making an exception for handle is simply not +// worth the trouble. +// +// borrowed cv* is an object manager so that we can use the general +// to_python mechanisms to convert raw Python object pointers to +// python, without the usual semantic problems of using raw pointers. + + +// Object Manager Concept requirements: +// +// T is an Object Manager +// p is a PyObject* +// x is a T +// +// * object_manager_traits::is_specialized == true +// +// * T(detail::borrowed_reference(p)) +// Manages p without checking its type +// +// * get_managed_object(x, boost::python::tag) +// Convertible to PyObject* +// +// Additional requirements if T can be converted from_python: +// +// * T(object_manager_traits::adopt(p)) +// steals a reference to p, or throws a TypeError exception if +// p doesn't have an appropriate type. May assume p is non-null +// +// * X::check(p) +// convertible to bool. True iff T(X::construct(p)) will not +// throw. + +// Forward declarations +// +namespace boost { namespace python +{ + namespace api + { + class object; + } +}} + +namespace boost { namespace python { namespace converter { + + +// Specializations for handle +template +struct handle_object_manager_traits + : pyobject_traits +{ + private: + typedef pyobject_traits base; + + public: + BOOST_STATIC_CONSTANT(bool, is_specialized = true); + + // Initialize with a null_ok pointer for efficiency, bypassing the + // null check since the source is always non-null. + static null_ok* adopt(PyObject* p) + { + return python::allow_null(base::checked_downcast(p)); + } +}; + +template +struct default_object_manager_traits +{ + BOOST_STATIC_CONSTANT( + bool, is_specialized = python::detail::is_borrowed_ptr::value + ); +}; + +template +struct object_manager_traits + : mpl::select_type< + is_handle::value + , handle_object_manager_traits + , default_object_manager_traits + >::type +{ +}; + +// +// Traits for detecting whether a type is an object manager or a +// (cv-qualified) reference to an object manager. +// + +template +struct is_object_manager +{ + BOOST_STATIC_CONSTANT( + bool, value = object_manager_traits::is_specialized); +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_reference_to_object_manager +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_object_manager + : is_object_manager +{ +}; + +template +struct is_reference_to_object_manager + : is_object_manager +{ +}; + +template +struct is_reference_to_object_manager + : is_object_manager +{ +}; + +template +struct is_reference_to_object_manager + : is_object_manager +{ +}; +# else + +namespace detail +{ + typedef char (&yes_reference_to_object_manager)[1]; + typedef char (&no_reference_to_object_manager)[2]; + + // A number of nastinesses go on here in order to work around MSVC6 + // bugs. + template + struct is_object_manager_help + { + typedef typename mpl::select_type< + is_object_manager::value + , yes_reference_to_object_manager + , no_reference_to_object_manager + >::type type; + + // If we just use the type instead of the result of calling this + // function, VC6 will ICE. + static type call(); + }; + + // A set of overloads for each cv-qualification. The same argument + // is passed twice: the first one is used to unwind the cv*, and the + // second one is used to avoid relying on partial ordering for + // overload resolution. + template + typename is_object_manager_help + is_object_manager_helper(U*, void*); + + template + typename is_object_manager_help + is_object_manager_helper(U const*, void const*); + + template + typename is_object_manager_help + is_object_manager_helper(U volatile*, void volatile*); + + template + typename is_object_manager_help + is_object_manager_helper(U const volatile*, void const volatile*); + + template + struct is_reference_to_object_manager_nonref + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template + struct is_reference_to_object_manager_ref + { + static T sample_object; + BOOST_STATIC_CONSTANT( + bool, value + = (sizeof(is_object_manager_helper(&sample_object, &sample_object).call()) + == sizeof(detail::yes_reference_to_object_manager) + ) + ); + }; +} + +template +struct is_reference_to_object_manager +{ + typedef typename mpl::select_type< + is_reference::value + , detail::is_reference_to_object_manager_ref + , detail::is_reference_to_object_manager_nonref + > chooser; + + BOOST_STATIC_CONSTANT(bool, value = chooser::type::value); +}; +# endif + +}}} // namespace boost::python::converter + +#endif // OBJECT_MANAGER_DWA2002614_HPP diff --git a/include/boost/python/converter/pyobject_traits.hpp b/include/boost/python/converter/pyobject_traits.hpp new file mode 100644 index 00000000..f975360c --- /dev/null +++ b/include/boost/python/converter/pyobject_traits.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. 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 PYOBJECT_TRAITS_DWA2002720_HPP +# define PYOBJECT_TRAITS_DWA2002720_HPP + +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct pyobject_traits; + +template <> +struct pyobject_traits +{ + // All objects are convertible to PyObject + static bool check(PyObject*) { return true; } + static PyObject* checked_downcast(PyObject* x) { return x; } +}; + +// +// Specializations +// + +# define BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(T) \ + template <> struct pyobject_traits \ + : pyobject_type {} + +// This is not an exhaustive list; should be expanded. +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Type); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(List); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Int); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Long); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Dict); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Tuple); + +}}} // namespace boost::python::converter + +#endif // PYOBJECT_TRAITS_DWA2002720_HPP diff --git a/include/boost/python/converter/pyobject_type.hpp b/include/boost/python/converter/pyobject_type.hpp new file mode 100644 index 00000000..63127d5b --- /dev/null +++ b/include/boost/python/converter/pyobject_type.hpp @@ -0,0 +1,36 @@ +// Copyright David Abrahams 2002. 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 PYOBJECT_TYPE_DWA2002720_HPP +# define PYOBJECT_TYPE_DWA2002720_HPP + +# include +# include + +namespace boost { namespace python { namespace converter { + +BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*); + +// Used as a base class for specializations which need to provide +// Python type checking capability. +template +struct pyobject_type +{ + static bool check(PyObject* x) + { + return ::PyObject_IsInstance(x, (PyObject*)pytype); + } + + static Object* checked_downcast(PyObject* x) + { + return python::downcast( + (checked_downcast_impl)(x, pytype) + ); + } +}; + +}}} // namespace boost::python::converter + +#endif // PYOBJECT_TYPE_DWA2002720_HPP diff --git a/include/boost/python/converter/pytype_arg_from_python.hpp b/include/boost/python/converter/pytype_arg_from_python.hpp new file mode 100644 index 00000000..ade4fd66 --- /dev/null +++ b/include/boost/python/converter/pytype_arg_from_python.hpp @@ -0,0 +1,99 @@ +// Copyright David Abrahams 2002. 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 PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP +# define PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP + +# include + +// +// arg_from_python converters for Python type wrappers, to be used as +// base classes for specializations. +// +namespace boost { namespace python { namespace converter { + +template +struct pytype_arg_from_python +{ + pytype_arg_from_python(PyObject*); + bool convertible() const; + private: + PyObject* m_src; +}; + +// rvalue converter base +template +struct pytype_wrapper_value_arg_from_python + : pytype_arg_from_python +{ + typedef Wrapper result_type; + + pytype_wrapper_value_arg_from_python(PyObject*); + Wrapper operator()(PyObject*) const; +}; + +// Special case for Wrapper& - must store an lvalue internally. This +// OK because the entire state of the object is actually in the Python +// object. +template +struct pytype_wrapper_ref_arg_from_python + : pytype_arg_from_python +{ + typedef Wrapper& result_type; + + pytype_wrapper_ref_arg_from_python(PyObject*); + Wrapper& operator()(PyObject*) const; + private: + mutable Wrapper m_result; +}; + +// +// implementations +// + +template +inline pytype_arg_from_python::pytype_arg_from_python(PyObject* x) + : m_src(x) +{ +} + +template +inline bool pytype_arg_from_python::convertible() const +{ + return PyObject_IsInstance(m_src, (PyObject*)python_type); +} + +template +pytype_wrapper_value_arg_from_python::pytype_wrapper_value_arg_from_python( + PyObject* p) + : pytype_arg_from_python(p) +{ +} + +template +Wrapper pytype_wrapper_value_arg_from_python::operator()( + PyObject* x) const +{ + return Wrapper(python::detail::borrowed_reference(x)); +} + +template +pytype_wrapper_ref_arg_from_python::pytype_wrapper_ref_arg_from_python( + PyObject* p) + : pytype_arg_from_python(p) + , m_result(python::detail::borrowed_reference(p)) +{ +} + +template +Wrapper& pytype_wrapper_ref_arg_from_python::operator()( + PyObject* x) const +{ + return m_result; +} + +}}} // namespace boost::python::converter + +#endif // PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP diff --git a/include/boost/python/converter/pytype_object_mgr_traits.hpp b/include/boost/python/converter/pytype_object_mgr_traits.hpp new file mode 100644 index 00000000..94cbae64 --- /dev/null +++ b/include/boost/python/converter/pytype_object_mgr_traits.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. 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 PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP +# define PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// Provide a forward declaration as a convenience for clients, who all +// need it. +template struct object_manager_traits; + +// Derive specializations of object_manager_traits from this class +// when T is an object manager for a particular Python type hierarchy. +// +template +struct pytype_object_manager_traits + : pyobject_type // provides check() +{ + BOOST_STATIC_CONSTANT(bool, is_specialized = true); + static inline python::detail::new_reference adopt(PyObject*); +}; + +// +// implementations +// +template +inline python::detail::new_reference pytype_object_manager_traits::adopt(PyObject* x) +{ + return python::detail::new_reference(python::pytype_check(pytype, x)); +} + +}}} // namespace boost::python::converter + +#endif // PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP diff --git a/include/boost/python/converter/registered.hpp b/include/boost/python/converter/registered.hpp new file mode 100644 index 00000000..2d3daa99 --- /dev/null +++ b/include/boost/python/converter/registered.hpp @@ -0,0 +1,54 @@ +// Copyright David Abrahams 2002. 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 REGISTERED_DWA2002710_HPP +# define REGISTERED_DWA2002710_HPP +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct registration; + +namespace detail +{ + template + struct registered_base + { + static registration const& converters; + }; +} + +template +struct registered + : detail::registered_base< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// collapses a few more types to the same static instance +template +struct registered : registered {}; +# endif + +// +// implementations +// +namespace detail +{ + template + registration const& registered_base::converters + = registry::lookup(type_id()); +} +}}} // namespace boost::python::converter + +#endif // REGISTERED_DWA2002710_HPP diff --git a/include/boost/python/converter/registered_pointee.hpp b/include/boost/python/converter/registered_pointee.hpp new file mode 100644 index 00000000..861cf724 --- /dev/null +++ b/include/boost/python/converter/registered_pointee.hpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. 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 REGISTERED_POINTEE_DWA2002710_HPP +# define REGISTERED_POINTEE_DWA2002710_HPP +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct registration; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct registered_pointee + : registered< + typename remove_pointer< + typename remove_cv< + typename remove_reference::type + >::type + >::type + > +{ +}; +# else +namespace detail +{ + template + struct registered_pointee_base + { + static registration const& converters; + }; +} + +template +struct registered_pointee + : detail::registered_pointee_base< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +// +// implementations +// +namespace detail +{ + template + registration const& registered_pointee_base::converters + = registry::lookup(pointer_type_id()); +} + +# endif +}}} // namespace boost::python::converter + +#endif // REGISTERED_POINTEE_DWA2002710_HPP diff --git a/include/boost/python/converter/registrations.hpp b/include/boost/python/converter/registrations.hpp new file mode 100644 index 00000000..af2dd510 --- /dev/null +++ b/include/boost/python/converter/registrations.hpp @@ -0,0 +1,67 @@ +// Copyright David Abrahams 2002. 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 REGISTRATIONS_DWA2002223_HPP +# define REGISTRATIONS_DWA2002223_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct lvalue_from_python_chain +{ + convertible_function convert; + lvalue_from_python_chain* next; +}; + +struct rvalue_from_python_chain +{ + convertible_function convertible; + constructor_function construct; + rvalue_from_python_chain* next; +}; + +struct registration +{ + explicit registration(type_info); + + const python::type_info target_type; + + // The chain of eligible from_python converters when an lvalue is required + lvalue_from_python_chain* lvalue_chain; + + // The chain of eligible from_python converters when an rvalue is acceptable + rvalue_from_python_chain* rvalue_chain; + + // The unique to_python converter for the associated C++ type. + to_python_function_t to_python; + + // The class object associated with this type + PyTypeObject* class_object; +}; + +// +// implementations +// +inline registration::registration(type_info target_type) + : target_type(target_type) + , lvalue_chain(0) + , rvalue_chain(0) + , to_python(0) + , class_object(0) +{} + +inline bool operator<(registration const& lhs, registration const& rhs) +{ + return lhs.target_type < rhs.target_type; +} + +}}} // namespace boost::python::converter + +#endif // REGISTRATIONS_DWA2002223_HPP diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp new file mode 100644 index 00000000..b71c949a --- /dev/null +++ b/include/boost/python/converter/registry.hpp @@ -0,0 +1,52 @@ +// 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 REGISTRY_DWA20011127_HPP +# define REGISTRY_DWA20011127_HPP +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct registration; + +// This namespace acts as a sort of singleton +namespace registry +{ + // Get the registration corresponding to the type, creating it if neccessary + BOOST_PYTHON_DECL registration const& lookup(type_info); + + // Return a pointer to the corresponding registration, if one exists + BOOST_PYTHON_DECL registration const* query(type_info); + + BOOST_PYTHON_DECL void insert(to_python_function_t, type_info); + + // Insert an lvalue from_python converter + BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info); + + // Insert an rvalue from_python converter + BOOST_PYTHON_DECL void insert( + convertible_function + , constructor_function + , type_info + ); + + // Insert an rvalue from_python converter at the tail of the + // chain. Used for implicit conversions + BOOST_PYTHON_DECL void push_back( + convertible_function + , constructor_function + , type_info + ); +} + +}}} // namespace boost::python::converter + +#endif // REGISTRY_DWA20011127_HPP diff --git a/include/boost/python/converter/return_from_python.hpp b/include/boost/python/converter/return_from_python.hpp new file mode 100755 index 00000000..f02f01d9 --- /dev/null +++ b/include/boost/python/converter/return_from_python.hpp @@ -0,0 +1,151 @@ +// Copyright David Abrahams 2002. 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 RETURN_FROM_PYTHON_DWA200265_HPP +# define RETURN_FROM_PYTHON_DWA200265_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct is_object_manager; + +namespace detail +{ + template + struct return_pointer_from_python + { + typedef T result_type; + T operator()(PyObject*) const; + }; + + template + struct return_reference_from_python + { + typedef T result_type; + T operator()(PyObject*) const; + }; + + template + struct return_rvalue_from_python + { + typedef typename call_traits::param_type result_type; + return_rvalue_from_python(); + result_type operator()(PyObject*); + private: + rvalue_from_python_data m_data; + }; + + template + struct return_object_manager_from_python + { + typedef T result_type; + result_type operator()(PyObject*) const; + }; + + template + struct select_return_from_python + { + BOOST_STATIC_CONSTANT( + bool, obj_mgr = is_object_manager::value); + + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ref = is_reference::value); + + typedef typename mpl::select_type< + obj_mgr + , return_object_manager_from_python + , typename mpl::select_type< + ptr + , return_pointer_from_python + , typename mpl::select_type< + ref + , return_reference_from_python + , return_rvalue_from_python + >::type + >::type + >::type type; + }; +} + +template +struct return_from_python + : detail::select_return_from_python::type +{ +}; + +// Specialization as a convenience for call and call_method +template <> +struct return_from_python +{ + typedef python::detail::returnable::type result_type; + + result_type operator()(PyObject* x) const + { + (void_result_from_python)(x); +# ifdef BOOST_NO_VOID_RETURNS + return result_type(); +# endif + } +}; + +// +// Implementations +// +namespace detail +{ + template + inline return_rvalue_from_python::return_rvalue_from_python() + : m_data( + const_cast(®istered::converters) + ) + { + } + + template + inline typename return_rvalue_from_python::result_type + return_rvalue_from_python::operator()(PyObject* obj) + { + return *(T*) + (rvalue_result_from_python)(obj, m_data.stage1); + } + + template + inline T return_reference_from_python::operator()(PyObject* obj) const + { + return python::detail::void_ptr_to_reference( + (reference_result_from_python)(obj, registered::converters) + , (T(*)())0); + } + + template + inline T return_pointer_from_python::operator()(PyObject* obj) const + { + return T( + (pointer_result_from_python)(obj, registered_pointee::converters) + ); + } + + template + inline T return_object_manager_from_python::operator()(PyObject* obj) const + { + return T( + object_manager_traits::adopt(obj) + ); + } +} + +}}} // namespace boost::python::converter + +#endif // RETURN_FROM_PYTHON_DWA200265_HPP diff --git a/include/boost/python/converter/rvalue_from_python_data.hpp b/include/boost/python/converter/rvalue_from_python_data.hpp new file mode 100644 index 00000000..72ea7bd7 --- /dev/null +++ b/include/boost/python/converter/rvalue_from_python_data.hpp @@ -0,0 +1,138 @@ +// Copyright David Abrahams 2002. 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 FROM_PYTHON_AUX_DATA_DWA2002128_HPP +# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP + +# include +# include +# include +# include +# include + +// Data management for potential rvalue conversions from Python to C++ +// types. When a client requests a conversion to T* or T&, we +// generally require that an object of type T exists in the source +// Python object, and the code here does not apply**. This implements +// conversions which may create new temporaries of type T. The classic +// example is a conversion which converts a Python tuple to a +// std::vector. Since no std::vector lvalue exists in the Python +// object -- it must be created "on-the-fly" by the converter, and +// which must manage the lifetime of the created object. +// +// Note that the client is not precluded from using a registered +// lvalue conversion to T in this case. In other words, we will +// happily accept a Python object which /does/ contain a std::vector +// lvalue, provided an appropriate converter is registered. So, while +// this is an rvalue conversion from the client's point-of-view, the +// converter registry may serve up lvalue or rvalue conversions for +// the target type. +// +// ** C++ argument from_python conversions to T const& are an +// exception to the rule for references: since in C++, const +// references can bind to temporary rvalues, we allow rvalue +// converters to be chosen when the target type is T const& for some +// T. +namespace boost { namespace python { namespace converter { + +// Conversions begin by filling in and returning a copy of this +// structure. The process looks up a converter in the rvalue converter +// registry for the target type. It calls the convertible() function +// of each registered converter, passing the source PyObject* as an +// argument, until a non-null result is returned. This result goes in +// the convertible field, and the converter's construct() function is +// stored in the construct field. +// +// If no appropriate converter is found, conversion fails and the +// convertible field is null. When used in argument conversion for +// wrapped C++ functions, it causes overload resolution to reject the +// current function but not to fail completely. If an exception is +// thrown, overload resolution stops and the exception propagates back +// through the caller. +// +// If an lvalue converter is matched, its convertible() function is +// expected to return a pointer to the stored T object; its +// construct() function will be NULL. The convertible() function of +// rvalue converters may return any non-singular pointer; the actual +// target object will only be available once the converter's +// construct() function is called. +struct rvalue_from_python_stage1_data +{ + void* convertible; + constructor_function construct; +}; + +// Augments rvalue_from_python_stage1_data by adding storage for +// constructing an object of remove_reference::type. The +// construct() function of rvalue converters (stored in m_construct +// above) will cast the rvalue_from_python_stage1_data to an +// appropriate instantiation of this template in order to access that +// storage. +template +struct rvalue_from_python_storage +{ + rvalue_from_python_stage1_data stage1; + + // Storage for the result, in case an rvalue must be constructed + typename python::detail::referent_storage< + typename add_reference::type + >::type storage; +}; + +// Augments rvalue_from_python_storage with a destructor. If +// stage1.convertible == storage.bytes, it indicates that an object of +// remove_reference::type has been constructed in storage and +// should will be destroyed in ~rvalue_from_python_data(). It is +// crucial that successful rvalue conversions establish this equality +// and that unsuccessful ones do not. +template +struct rvalue_from_python_data : rvalue_from_python_storage +{ +# if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \ + && (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \ + && (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) + // This must always be a POD struct with m_data its first member. + BOOST_STATIC_ASSERT(offsetof(rvalue_from_python_storage,stage1) == 0); +# endif + + // The usual constructor + rvalue_from_python_data(rvalue_from_python_stage1_data const&); + + // This constructor just sets m_convertible -- used by + // implicitly_convertible<> to perform the final step of the + // conversion, where the construct() function is already known. + rvalue_from_python_data(void* convertible); + + // Destroys any object constructed in the storage. + ~rvalue_from_python_data(); + private: + typedef typename add_reference::type>::type ref_type; +}; + +// +// Implementataions +// +template +inline rvalue_from_python_data::rvalue_from_python_data(rvalue_from_python_stage1_data const& stage1) +{ + this->stage1 = stage1; +} + +template +inline rvalue_from_python_data::rvalue_from_python_data(void* convertible) +{ + this->stage1.convertible = convertible; +} + +template +inline rvalue_from_python_data::~rvalue_from_python_data() +{ + if (this->stage1.convertible == this->storage.bytes) + python::detail::destroy_referent(this->storage.bytes); +} + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/include/boost/python/data_members.hpp b/include/boost/python/data_members.hpp new file mode 100644 index 00000000..01190811 --- /dev/null +++ b/include/boost/python/data_members.hpp @@ -0,0 +1,111 @@ +// Copyright David Abrahams 2002. 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 DATA_MEMBERS_DWA2002328_HPP +# define DATA_MEMBERS_DWA2002328_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct member + { + static PyObject* get(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies) + { + arg_from_python c0(PyTuple_GET_ITEM(args_, 0)); + if (!c0.convertible()) return 0; + + // find the result converter + typedef typename Policies::result_converter result_converter; + typedef typename boost::add_reference::type source; + typename mpl::apply1::type cr; + if (!cr.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + PyObject* result = cr( (c0(PyTuple_GET_ITEM(args_, 0)))->*pm ); + + return policies.postcall(args_, result); + } + + static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies) + { + // check that each of the arguments is convertible + arg_from_python c0(PyTuple_GET_ITEM(args_, 0)); + if (!c0.convertible()) return 0; + + typedef typename add_const::type target1; + typedef typename add_reference::type target; + arg_from_python c1(PyTuple_GET_ITEM(args_, 1)); + + if (!c1.convertible()) return 0; + + if (!policies.precall(args_)) return 0; + + (c0(PyTuple_GET_ITEM(args_, 0)))->*pm = c1(PyTuple_GET_ITEM(args_, 1)); + + return policies.postcall(args_, detail::none()); + } + }; +} + +template +object make_getter(D C::*pm) +{ + typedef return_value_policy default_policy; + + return objects::function_object( + ::boost::bind( + &detail::member::get, pm, _1, _2 + , default_policy()) + , 1); + +} + +template +object make_getter(D C::*pm, Policies const& policies) +{ + return objects::function_object( + ::boost::bind( + &detail::member::get, pm, _1, _2 + , policies) + , 1); +} + +template +object make_setter(D C::*pm) +{ + return objects::function_object( + ::boost::bind( + &detail::member::set, pm, _1, _2 + , default_call_policies()) + , 2); +} + +template +object make_setter(D C::*pm, Policies const& policies) +{ + return objects::function_object( + ::boost::bind( + &detail::member::set, pm, _1, _2 + , policies) + , 2); +} + + +}} // namespace boost::python + +#endif // DATA_MEMBERS_DWA2002328_HPP diff --git a/include/boost/python/def.hpp b/include/boost/python/def.hpp new file mode 100644 index 00000000..c6b8bb54 --- /dev/null +++ b/include/boost/python/def.hpp @@ -0,0 +1,100 @@ +// Copyright David Abrahams 2002. 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 DEF_DWA200292_HPP +# define DEF_DWA200292_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + void BOOST_PYTHON_DECL scope_setattr_doc(char const* name, object const& obj, char const* doc); + + template + void + dispatch_def( + void const*, + char const* name, + Fn fn, + CallPolicyOrDoc const& policy_or_doc, + char const* doc) + { + typedef detail::def_helper helper; + + detail::scope_setattr_doc( + name, boost::python::make_function(fn, helper::get_policy(policy_or_doc)), + helper::get_doc(policy_or_doc, doc)); + } + + template + void dispatch_def( + detail::func_stubs_base const*, + char const* name, + SigT sig, + StubsT const& stubs, + CallPolicyOrDoc const& policy_or_doc, + char const* doc = 0) + { + typedef detail::def_helper helper; + + // convert sig to a type_list (see detail::get_signature in signature.hpp) + // before calling detail::define_with_defaults. + + scope current; + detail::define_with_defaults( + name, stubs, helper::get_policy(policy_or_doc), + current, detail::get_signature(sig), + helper::get_doc(policy_or_doc, doc)); + } +} + +template +void def(char const* name, Fn fn) +{ + detail::scope_setattr_doc(name, boost::python::make_function(fn), 0); +} + +template +void def(char const* name, Arg1T arg1, Arg2T const& arg2) +{ + // The arguments may be: + // arg1: function or signature + // arg2: policy or docstring or stubs + + detail::dispatch_def(&arg2, name, arg1, arg2, (char*)0); +} + +template +void def(char const* name, Arg1T arg1, Arg2T const& arg2, Arg3T const& arg3) +{ + // The arguments may be: + // arg1: function or signature + // arg2: policy or docstring or stubs + // arg3: policy or docstring + + detail::dispatch_def(&arg2, name, arg1, arg2, arg3); +} + +template +void def(char const* name, Arg1T arg1, Arg2T const& arg2, Arg3T const& arg3, char const* doc) +{ + // The arguments are definitely: + // arg1: signature + // arg2: stubs + // arg3: policy + + detail::dispatch_def(&arg2, name, arg1, arg2, arg3, doc); +} + +}} // namespace boost::python + +#endif // DEF_DWA200292_HPP diff --git a/include/boost/python/detail/aix_init_module.hpp b/include/boost/python/detail/aix_init_module.hpp new file mode 100644 index 00000000..6eda62ea --- /dev/null +++ b/include/boost/python/detail/aix_init_module.hpp @@ -0,0 +1,24 @@ +// Copyright David Abrahams 2002. 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 AIX_INIT_MODULE_DWA2002529_HPP +# define AIX_INIT_MODULE_DWA2002529_HPP +# ifdef _AIX +# include +# include + +namespace boost { namespace python { namespace detail { + +extern "C" +{ + typedef PyObject* (*so_load_function)(char*,char*,FILE*); +} + +void aix_init_module(so_load_function, char const* name, void (*init_module)()); + +}}} // namespace boost::python::detail +# endif + +#endif // AIX_INIT_MODULE_DWA2002529_HPP diff --git a/include/boost/python/detail/api_placeholder.hpp b/include/boost/python/detail/api_placeholder.hpp new file mode 100644 index 00000000..9a4672ab --- /dev/null +++ b/include/boost/python/detail/api_placeholder.hpp @@ -0,0 +1,14 @@ +#ifndef BOOST_PYTHON_API_PLACE_HOLDER_HPP +#define BOOST_PYTHON_API_PLACE_HOLDER_HPP + +namespace boost { namespace python { + + inline long len(object const& obj) + { + long result = PyObject_Length(obj.ptr()); + if (PyErr_Occurred()) throw_error_already_set(); + return result; + } +}} // namespace boost::python + +#endif // BOOST_PYTHON_API_PLACE_HOLDER_HPP diff --git a/include/boost/python/detail/arg_tuple_size.hpp b/include/boost/python/detail/arg_tuple_size.hpp new file mode 100644 index 00000000..183e957f --- /dev/null +++ b/include/boost/python/detail/arg_tuple_size.hpp @@ -0,0 +1,127 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// (C) 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. +// +// This work was funded in part by Lawrence Berkeley National Labs +// +// This file generated for 5-argument member functions and 6-argument free +// functions by gen_arg_tuple_size.python + +#ifndef ARG_TUPLE_SIZE_DWA20011201_HPP +# define ARG_TUPLE_SIZE_DWA20011201_HPP + +# include + +# include +# include + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// Computes (at compile-time) the number of elements that a Python +// argument tuple must have in order to be passed to a wrapped C++ +// (member) function of the given type. +template struct arg_tuple_size; + +// We will use the "sizeof() trick" to work around the lack of +// partial specialization in MSVC6 and its broken-ness in borland. +// See http://opensource.adobe.com or +// http://groups.yahoo.com/group/boost/message/5441 for +// more examples + +// The following helper functions are never actually called, since +// they are only used within a sizeof() expression, but the type of +// their return value is used to discriminate between various free +// and member function pointers at compile-time. + +// Specializations for function pointers +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, , BOOST_PYTHON_FUNCTION_POINTER)) +# include BOOST_PP_ITERATE() + +// Specializations for member function pointers +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_CV_COUNT - 1, , BOOST_PYTHON_POINTER_TO_MEMBER)) +# include BOOST_PP_ITERATE() + +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template +struct arg_tuple_size +{ + // The sizeof() magic happens here + BOOST_STATIC_CONSTANT(std::size_t, value + = sizeof(arg_tuple_size_helper(F(0)).elements) - 1); +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}}} // namespace boost::python::detail + +#endif // ARG_TUPLE_SIZE_DWA20011201_HPP + +// --------------- function pointers --------------- // +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +# line BOOST_PP_LINE(__LINE__, arg_tuple_size.hpp(function pointers)) + +# define N BOOST_PP_ITERATION() + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = N); +}; + +# else + +template +char_array arg_tuple_size_helper( + R (*)(BOOST_PYTHON_UNARY_ENUM(N, A))); + +# endif // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +# undef N + +// --------------- pointers-to-members --------------- // +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_POINTER_TO_MEMBER +// Outer iteration over cv-qualifications + +# define BOOST_PP_ITERATION_PARAMS_2 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 && BOOST_PP_RELATIVE_FLAGS(1) == BOOST_PYTHON_POINTER_TO_MEMBER +# line BOOST_PP_LINE(__LINE__, arg_tuple_size.hpp(pointers-to-members)) +// Inner iteration over arities + +# define N BOOST_PP_ITERATION() +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template +struct arg_tuple_size +{ + BOOST_STATIC_CONSTANT(std::size_t, value = N + 1U); +}; + +# else + +template +char_array arg_tuple_size_helper( + R (T::*)(BOOST_PYTHON_UNARY_ENUM(N, A)) Q); + +# endif // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +# undef Q +# undef N + +#endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/include/boost/python/detail/borrowed_ptr.hpp b/include/boost/python/detail/borrowed_ptr.hpp new file mode 100755 index 00000000..dc50c634 --- /dev/null +++ b/include/boost/python/detail/borrowed_ptr.hpp @@ -0,0 +1,112 @@ +#ifndef BORROWED_PTR_DWA20020601_HPP +# define BORROWED_PTR_DWA20020601_HPP +// Copyright David Abrahams 2002. 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 +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +template class borrowed +{ + typedef T type; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_borrowed_ptr +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +# if !defined(__MWERKS__) || __MWERKS__ > 0x3000 +template +struct is_borrowed_ptr*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_borrowed_ptr const*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_borrowed_ptr volatile*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_borrowed_ptr const volatile*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; +# else +template +struct is_borrowed +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; +template +struct is_borrowed > +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; +template +struct is_borrowed_ptr + : is_borrowed::type> +{ +}; +# endif + +# else // no partial specialization + +typedef char (&yes_borrowed_ptr_t)[1]; +typedef char (&no_borrowed_ptr_t)[2]; + +no_borrowed_ptr_t is_borrowed_ptr_test(...); + +template +typename mpl::select_type< + is_pointer::value + , T + , int + >::type +is_borrowed_ptr_test1(boost::type); + +template +yes_borrowed_ptr_t is_borrowed_ptr_test(borrowed const volatile*); + +template +class is_borrowed_ptr +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_borrowed_ptr_test(is_borrowed_ptr_test1(boost::type()))) + == sizeof(detail::yes_borrowed_ptr_t))); +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +} + +template +inline T* get_managed_object(detail::borrowed const volatile* p, tag_t) +{ + return (T*)p; +} + +}} // namespace boost::python::detail + +#endif // #ifndef BORROWED_PTR_DWA20020601_HPP diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp new file mode 100644 index 00000000..322e1342 --- /dev/null +++ b/include/boost/python/detail/caller.hpp @@ -0,0 +1,107 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// (C) Copyright David Abrahams 2000. 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. +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. +// +// This file generated for 10-argument member functions and 11-argument free +// functions by gen_caller.python + +# ifndef CALLER_DWA20011214_HPP +# define CALLER_DWA20011214_HPP + +# include +# include +# include + +# include +# include + +# // temp: include + +# include +# include +# include + +namespace boost { namespace python +{ + template struct to_python; +}} + +namespace boost { namespace python { namespace detail { + +struct caller +{ + typedef PyObject* result_type; + + // function pointers +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, , BOOST_PYTHON_FUNCTION_POINTER)) +# include BOOST_PP_ITERATE() + + // pointers-to-members +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, 3, , BOOST_PYTHON_POINTER_TO_MEMBER)) +# include BOOST_PP_ITERATE() + +}; + +}}} // namespace boost::python::detail + +# endif // CALLER_DWA20011214_HPP + +/* ---------- function pointers --------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +# line BOOST_PP_LINE(__LINE__, detail/caller.hpp(function pointers)) + +# define N BOOST_PP_ITERATION() + +template < + class P, class R + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_UNARY_ENUM(N, class A) + > +PyObject* operator()( + R (*pf)(BOOST_PYTHON_UNARY_ENUM(N, A)) + , PyObject* args + , PyObject* keywords + , P const& policies) const +{ + return returning::call(pf, args, keywords, &policies); +} + +# undef N + +/* ---------- pointers-to-members ---------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_POINTER_TO_MEMBER +// outer over cv-qualifiers + +# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 +// inner over arities + +#define N BOOST_PP_ITERATION() +#define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + +template < + class P, class R, class T + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_UNARY_ENUM(N, class A) + > +PyObject* operator()( + R (T::*pmf)(BOOST_PYTHON_UNARY_ENUM(N, A)) Q + , PyObject* args, PyObject* keywords + , P const& policies + ) const +{ + return returning::call(pmf, args, keywords, &policies); +} + +#undef N +#undef Q + +#endif diff --git a/include/boost/python/detail/construct.hpp b/include/boost/python/detail/construct.hpp new file mode 100644 index 00000000..f7b747f6 --- /dev/null +++ b/include/boost/python/detail/construct.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. 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 CONSTRUCT_REFERENCE_DWA2002716_HPP +# define CONSTRUCT_REFERENCE_DWA2002716_HPP + +namespace boost { namespace python { namespace detail { + +template +void construct_pointee(void* storage, Arg& x +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + , T const volatile* +# else + , T const* +# endif + ) +{ + new (storage) T(x); +} + +template +void construct_referent_impl(void* storage, Arg& x, T&(*)()) +{ + construct_pointee(storage, x, (T*)0); +} + +template +void construct_referent(void* storage, Arg const& x, T(*tag)() = 0) +{ + construct_referent_impl(storage, x, tag); +} + +template +void construct_referent(void* storage, Arg& x, T(*tag)() = 0) +{ + construct_referent_impl(storage, x, tag); +} + +}}} // namespace boost::python::detail + +#endif // CONSTRUCT_REFERENCE_DWA2002716_HPP diff --git a/include/boost/python/detail/decorated_type_id.hpp b/include/boost/python/detail/decorated_type_id.hpp new file mode 100755 index 00000000..c43a4160 --- /dev/null +++ b/include/boost/python/detail/decorated_type_id.hpp @@ -0,0 +1,77 @@ +// Copyright David Abrahams 2002. 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 DECORATED_TYPE_ID_DWA2002517_HPP +# define DECORATED_TYPE_ID_DWA2002517_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +struct decorated_type_info : totally_ordered +{ + enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; + + decorated_type_info(type_info, decoration = decoration()); + + inline bool operator<(decorated_type_info const& rhs) const; + inline bool operator==(decorated_type_info const& rhs) const; + + friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, decorated_type_info const&); + + operator type_info const&() const; + private: // type + typedef type_info base_id_t; + + private: // data members + decoration m_decoration; + base_id_t m_base_type; +}; + +template +inline decorated_type_info decorated_type_id(boost::type* = 0) +{ + return decorated_type_info( + type_id() + , decorated_type_info::decoration( + (is_const::value || python::detail::is_reference_to_const::value + ? decorated_type_info::const_ : 0) + | (is_volatile::value || python::detail::is_reference_to_volatile::value + ? decorated_type_info::volatile_ : 0) + | (is_reference::value ? decorated_type_info::reference : 0) + ) + ); +} + +inline decorated_type_info::decorated_type_info(type_info base_t, decoration decoration) + : m_decoration(decoration) + , m_base_type(base_t) +{ +} + +inline bool decorated_type_info::operator<(decorated_type_info const& rhs) const +{ + return m_decoration < rhs.m_decoration + || m_decoration == rhs.m_decoration + && m_base_type < rhs.m_base_type; +} + +inline bool decorated_type_info::operator==(decorated_type_info const& rhs) const +{ + return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type; +} + +inline decorated_type_info::operator type_info const&() const +{ + return m_base_type; +} + +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, decorated_type_info const&); + +}}} // namespace boost::python::detail + +#endif // DECORATED_TYPE_ID_DWA2002517_HPP diff --git a/include/boost/python/detail/def_helper.hpp b/include/boost/python/detail/def_helper.hpp new file mode 100644 index 00000000..1222f71b --- /dev/null +++ b/include/boost/python/detail/def_helper.hpp @@ -0,0 +1,61 @@ +// Copyright David Abrahams 2002. 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 DEF_HELPER_DWA200287_HPP +# define DEF_HELPER_DWA200287_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// +// def_helper -- +// +// A helper for def() functions which determines how to interpret +// an argument of type T which could be either CallPolicies or a +// string literal representing a docstring. +// +// Generates two static functions: +// +// get_policy(x), where x is of type T, returns a policies +// object: either a reference to x or default_call_policies() +// if x is a string literal. +// +// get_doc(x, s), where s convertible to char const*, returns x +// if x is a string literal, s otherwise. + +template +struct def_helper_impl +{ + template + static P const& get_policy(P const& x) { return x; } + + template + static char const* get_doc(P const&, char const* doc) { return doc; } +}; + +template <> +struct def_helper_impl +{ + static python::default_call_policies get_policy(char const*) { return default_call_policies(); } + static char const* get_doc(char const* doc, char const*) { return doc; } +}; + +template +struct def_helper + : def_helper_impl< + type_traits::ice_or< + is_string_literal::value + , is_same::value + , is_same::value +>::value +> +{}; + +}}} // namespace boost::python::detail + +#endif // DEF_HELPER_DWA200287_HPP diff --git a/include/boost/python/detail/defaults_def.hpp b/include/boost/python/detail/defaults_def.hpp new file mode 100644 index 00000000..7efbcb70 --- /dev/null +++ b/include/boost/python/detail/defaults_def.hpp @@ -0,0 +1,253 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002. 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. +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef DEFAULTS_DEF_JDG20020811_HPP +#define DEFAULTS_DEF_JDG20020811_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace python { + +struct module; + +namespace objects +{ + struct class_base; +} + +namespace detail { + +template +static void name_space_def( + NameSpaceT& name_space, + char const* name, + Func f, + CallPolicies const& policies, + char const* doc, + objects::class_base* + ) +{ + name_space.def( + name, f, policies, doc); +} + +template +static void name_space_def( + object& name_space, + char const* name, + Func f, + CallPolicies const& policies, + char const* doc, + ... + ) +{ + scope within(name_space); + + def(name, f, policies, doc); +} + +// For backward compatibility +template +static void name_space_def( + NameSpaceT& name_space, + char const* name, + Func f, + CallPolicies const& policies, + char const* doc, + module* + ) +{ + name_space.def( + name, f, policies, doc); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// This Boost PP code generates expansions for +// +// template +// inline void +// define_stub_function( +// char const* name, StubsT s, NameSpaceT& name_space, boost::mpl::int_t) +// { +// name_space.def(name, &StubsT::func_N); +// } +// +// where N runs from 0 to BOOST_PYTHON_MAX_ARITY +// +// The set of overloaded functions (define_stub_function) expects: +// +// 1. char const* name: function name that will be visible to python +// 2. StubsT: a function stubs struct (see defaults_gen.hpp) +// 3. NameSpaceT& name_space: a python::class_ or python::module instance +// 4. int_t: the Nth overloaded function (StubsT::func_N) +// (see defaults_gen.hpp) +// 5. char const* name: doc string +// +/////////////////////////////////////////////////////////////////////////////// +template +struct define_stub_function {}; + +#define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, )) + +#include BOOST_PP_ITERATE() + +/////////////////////////////////////////////////////////////////////////////// +// +// define_with_defaults_helper +// +// This helper template struct does the actual recursive definition. +// There's a generic version define_with_defaults_helper and a +// terminal case define_with_defaults_helper<0>. The struct and its +// specialization has a sole static member function def that expects: +// +// 1. char const* name: function name that will be visible to python +// 2. StubsT: a function stubs struct (see defaults_gen.hpp) +// 3. NameSpaceT& name_space: a python::class_ or python::module instance +// 4. char const* name: doc string +// +// The def static member function calls a corresponding +// define_stub_function. The general case recursively calls +// define_with_defaults_helper::def until it reaches the +// terminal case case define_with_defaults_helper<0>. +// +/////////////////////////////////////////////////////////////////////////////// + template + struct define_with_defaults_helper { + + template + static void + def( + char const* name, + StubsT stubs, + CallPolicies const& policies, + NameSpaceT& name_space, + char const* doc) + { + // define the NTH stub function of stubs + define_stub_function::define(name, stubs, policies, name_space, doc); + // call the next define_with_defaults_helper + define_with_defaults_helper::def(name, stubs, policies, name_space, doc); + } + }; + +/////////////////////////////////////// + template <> + struct define_with_defaults_helper<0> { + + template + static void + def( + char const* name, + StubsT stubs, + CallPolicies const& policies, + NameSpaceT& name_space, + char const* doc) + { + // define the Oth stub function of stubs + define_stub_function<0>::define(name, stubs, policies, name_space, doc); + // return + } + }; + +/////////////////////////////////////////////////////////////////////////////// +// +// define_with_defaults +// +// 1. char const* name: function name that will be visible to python +// 2. StubsT: a function stubs struct (see defaults_gen.hpp) +// 3. CallPolicies& policies: Call policies +// 4. NameSpaceT& name_space: a python::class_ or python::module instance +// 5. SigT sig: Function signature typelist (see defaults_gen.hpp) +// 6. char const* name: doc string +// +// This is the main entry point. This function recursively defines all +// stub functions of StubT (see defaults_gen.hpp) in NameSpaceT name_space which +// can be either a python::class_ or a python::module. The sig argument +// is a typelist that specifies the return type, the class (for member +// functions, and the arguments. Here are some SigT examples: +// +// int foo(int) mpl::type_list +// void bar(int, int) mpl::type_list +// void C::foo(int) mpl::type_list +// +/////////////////////////////////////////////////////////////////////////////// + template + inline void + define_with_defaults( + char const* name, + StubsT, + CallPolicies const& policies, + NameSpaceT& name_space, + SigT sig, + char const* doc) + { + typedef typename boost::python::detail::type_at<0, SigT>::type nth_type; + typedef typename StubsT::v_type v_type; + typedef typename StubsT::nv_type nv_type; + + typedef typename mpl::select_type< + boost::is_same::value + , v_type + , nv_type + >::type stubs_type; + + BOOST_STATIC_ASSERT( + (stubs_type::max_args) <= + boost::python::detail::type_list_size::value); + + typedef typename stubs_type::template gen gen_type; + define_with_defaults_helper::def + (name, gen_type(), policies, name_space, doc); + } + +} // namespace detail + +}} // namespace boost::python + +/////////////////////////////////////////////////////////////////////////////// +#endif // DEFAULTS_DEF_JDG20020811_HPP + +#else // defined(BOOST_PP_IS_ITERATING) +// PP vertical iteration code + + +template <> +struct define_stub_function { + template + static void define( + char const* name, + StubsT, + CallPolicies const& policies, + NameSpaceT& name_space, + char const* doc + ) + { + detail::name_space_def(name_space, + name, + &StubsT::BOOST_PP_CAT(func_, BOOST_PP_ITERATION()), + policies, + doc, &name_space); + } +}; + +#endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/include/boost/python/detail/defaults_gen.hpp b/include/boost/python/detail/defaults_gen.hpp new file mode 100644 index 00000000..b1ed0125 --- /dev/null +++ b/include/boost/python/detail/defaults_gen.hpp @@ -0,0 +1,287 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002. 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 DEFAULTS_GEN_JDG20020807_HPP +#define DEFAULTS_GEN_JDG20020807_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace python { namespace detail { + +/////////////////////////////////////////////////////////////////////////////// +// +// func_stubs_base is used as a base class for all function stubs. +// +/////////////////////////////////////////////////////////////////////////////// +struct func_stubs_base {}; + +}}} // namespace boost::python::detail + + +/////////////////////////////////////////////////////////////////////////////// +#define BPL_IMPL_TYPEDEF_GEN(z, INDEX, DATA) \ + typedef typename boost::python::detail::type_at \ + < \ + BOOST_PP_ADD(INDEX, DATA), \ + SigT \ + >::type BOOST_PP_CAT(T, INDEX); \ + +#define BPL_IMPL_FUNC_WRAPPER_GEN(z, index, DATA) \ + static RT BOOST_PP_CAT(func_, index) ( \ + BOOST_PYTHON_BINARY_ENUM( \ + BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), T, arg) \ + ) \ + { \ + BOOST_PP_TUPLE_ELEM(3, 2, DATA) \ + BOOST_PP_TUPLE_ELEM(3, 0, DATA) \ + ( \ + BOOST_PP_ENUM_PARAMS( \ + BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), \ + arg \ + ) \ + ); \ + } + +#define BPL_IMPL_GEN_FUNCTION(FNAME, FSTUBS_NAME, N_ARGS, N_DFLTS, RETURN) \ + struct FSTUBS_NAME { \ + \ + BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(N_DFLTS)); \ + BOOST_STATIC_CONSTANT(int, max_args = n_funcs); \ + \ + template \ + struct gen { \ + \ + typedef typename boost::python::detail::type_at<0, SigT>::type RT; \ + \ + BOOST_PP_REPEAT_2ND \ + ( \ + N_ARGS, \ + BPL_IMPL_TYPEDEF_GEN, \ + 1 \ + ) \ + \ + BOOST_PP_REPEAT_2ND \ + ( \ + BOOST_PP_INC(N_DFLTS), \ + BPL_IMPL_FUNC_WRAPPER_GEN, \ + (FNAME, BOOST_PP_SUB(N_ARGS, N_DFLTS), RETURN) \ + ) \ + }; \ + }; \ + +/////////////////////////////////////////////////////////////////////////////// +#define BPL_IMPL_MEM_FUNC_WRAPPER_GEN(z, index, DATA) \ + static RT BOOST_PP_CAT(func_, index) ( \ + ClassT& obj BOOST_PP_COMMA_IF( \ + BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index)) \ + BOOST_PYTHON_BINARY_ENUM( \ + BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), T, arg) \ + ) \ + { \ + BOOST_PP_TUPLE_ELEM(3, 2, DATA) obj.BOOST_PP_TUPLE_ELEM(3, 0, DATA)( \ + BOOST_PP_ENUM_PARAMS( \ + BOOST_PP_ADD(BOOST_PP_TUPLE_ELEM(3, 1, DATA), index), arg \ + ) \ + ); \ + } + +#define BPL_IMPL_GEN_MEM_FUNCTION(FNAME, FSTUBS_NAME, N_ARGS, N_DFLTS, RETURN) \ + struct FSTUBS_NAME { \ + \ + BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(N_DFLTS)); \ + BOOST_STATIC_CONSTANT(int, max_args = n_funcs + 1); \ + \ + template \ + struct gen { \ + \ + typedef typename boost::python::detail::type_at<0, SigT>::type RT; \ + typedef typename boost::python::detail::type_at<1, SigT>::type ClassT; \ + \ + BOOST_PP_REPEAT_2ND \ + ( \ + N_ARGS, \ + BPL_IMPL_TYPEDEF_GEN, \ + 2 \ + ) \ + \ + BOOST_PP_REPEAT_2ND \ + ( \ + BOOST_PP_INC(N_DFLTS), \ + BPL_IMPL_MEM_FUNC_WRAPPER_GEN, \ + (FNAME, BOOST_PP_SUB(N_ARGS, N_DFLTS), RETURN) \ + ) \ + }; \ + }; + + +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_MSVC) + +#define BPL_IMPL_GEN_FUNCTION_STUB(FNAME, FSTUBS_NAME, N_ARGS, N_DFLTS) \ + BPL_IMPL_GEN_FUNCTION \ + (FNAME, BOOST_PP_CAT(FSTUBS_NAME, _NV), N_ARGS, N_DFLTS, return) \ + BPL_IMPL_GEN_FUNCTION \ + (FNAME, BOOST_PP_CAT(FSTUBS_NAME, _V), N_ARGS, N_DFLTS, ;) \ + struct FSTUBS_NAME \ + : public boost::python::detail::func_stubs_base { \ + \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _NV) nv_type; \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _V) v_type; \ + }; \ + +/////////////////////////////////////////////////////////////////////////////// +#define BPL_IMPL_GEN_MEM_FUNCTION_STUB(FNAME, FSTUBS_NAME, N_ARGS, N_DFLTS) \ + BPL_IMPL_GEN_MEM_FUNCTION \ + (FNAME, BOOST_PP_CAT(FSTUBS_NAME, _NV), N_ARGS, N_DFLTS, return) \ + BPL_IMPL_GEN_MEM_FUNCTION \ + (FNAME, BOOST_PP_CAT(FSTUBS_NAME, _V), N_ARGS, N_DFLTS, ;) \ + struct FSTUBS_NAME \ + : public boost::python::detail::func_stubs_base { \ + \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _NV) nv_type; \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _V) v_type; \ + }; \ + +#else + +/////////////////////////////////////////////////////////////////////////////// +#define BPL_IMPL_GEN_FUNCTION_STUB(FNAME, FSTUBS_NAME, N_ARGS, N_DFLTS) \ + BPL_IMPL_GEN_FUNCTION \ + (FNAME, BOOST_PP_CAT(FSTUBS_NAME, _NV), N_ARGS, N_DFLTS, return) \ + struct FSTUBS_NAME \ + : public boost::python::detail::func_stubs_base { \ + \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _NV) nv_type; \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _NV) v_type; \ + }; \ + +/////////////////////////////////////////////////////////////////////////////// +#define BPL_IMPL_GEN_MEM_FUNCTION_STUB(FNAME, FSTUBS_NAME, N_ARGS, N_DFLTS) \ + BPL_IMPL_GEN_MEM_FUNCTION \ + (FNAME, BOOST_PP_CAT(FSTUBS_NAME, _NV), N_ARGS, N_DFLTS, return) \ + struct FSTUBS_NAME \ + : public boost::python::detail::func_stubs_base { \ + \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _NV) nv_type; \ + typedef BOOST_PP_CAT(FSTUBS_NAME, _NV) v_type; \ + }; \ + +#endif // defined(BOOST_MSVC) + +/////////////////////////////////////////////////////////////////////////////// +// +// MAIN MACROS +// +// Given GENERATOR_NAME, FNAME, MIN_ARGS and MAX_ARGS, These macros +// generate function stubs that forward to a function or member function +// named FNAME. MAX_ARGS is the arity of the function or member function +// FNAME. FNAME can have default arguments. MIN_ARGS is the minimum +// arity that FNAME can accept. +// +// There are two versions: +// +// 1. BOOST_PYTHON_FUNCTION_OVERLOADS for free functions +// 2. BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS for member functions. +// +// For instance, given a function: +// +// int +// foo(int a, char b = 1, unsigned c = 2, double d = 3) +// { +// return a + b + c + int(d); +// } +// +// The macro invocation: +// +// BOOST_PYTHON_FUNCTION_OVERLOADS(foo_stubs, foo, 1, 4) +// +// Generates this code: +// +// struct foo_stubs_NV { +// +// static const int n_funcs = 4; +// static const int max_args = n_funcs; +// +// template +// struct gen { +// +// typedef typename mpl::at<0, SigT>::type RT; +// typedef typename mpl::at<1, SigT>::type T0; +// typedef typename mpl::at<2, SigT>::type T1; +// typedef typename mpl::at<3, SigT>::type T2; +// typedef typename mpl::at<4, SigT>::type T3; +// +// static RT func_0(T0 arg0) +// { return foo(arg0); } +// +// static RT func_1(T0 arg0, T1 arg1) +// { return foo(arg0, arg1); } +// +// static RT func_2(T0 arg0, T1 arg1, T2 arg2) +// { return foo(arg0, arg1, arg2); } +// +// static RT func_3(T0 arg0, T1 arg1, T2 arg2, T3 arg3) +// { return foo(arg0, arg1, arg2, arg3); } +// }; +// }; +// +// struct foo_stubs +// : public boost::python::detail::func_stubs_base { +// +// typedef foo_stubs_NV nv_type; +// typedef foo_stubs_NV v_type; +// }; +// +// The typedefs nv_type and v_type are used to handle compilers that +// do not support void returns. The example above typedefs nv_type +// and v_type to foo_stubs_NV. On compilers that do not support +// void returns, there are two versions: foo_stubs_NV and foo_stubs_V. +// The "V" version is almost identical to the "NV" version except +// for the return type (void) and the lack of the return keyword. +// +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_PYTHON_FUNCTION_OVERLOADS(GENERATOR_NAME, FNAME, MIN_ARGS, MAX_ARGS) \ + BPL_IMPL_GEN_FUNCTION_STUB \ + ( \ + FNAME, \ + GENERATOR_NAME, \ + MAX_ARGS, \ + BOOST_PP_SUB(MAX_ARGS, MIN_ARGS) \ + ) + +#define BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(GENERATOR_NAME, FNAME, MIN_ARGS, MAX_ARGS) \ + BPL_IMPL_GEN_MEM_FUNCTION_STUB \ + ( \ + FNAME, \ + GENERATOR_NAME, \ + MAX_ARGS, \ + BOOST_PP_SUB(MAX_ARGS, MIN_ARGS) \ + ) + +// deprecated macro names (to be removed) +#define BOOST_PYTHON_FUNCTION_GENERATOR BOOST_PYTHON_FUNCTION_OVERLOADS +#define BOOST_PYTHON_MEM_FUN_GENERATOR BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + +/////////////////////////////////////////////////////////////////////////////// +#endif // DEFAULTS_GEN_JDG20020807_HPP + + diff --git a/include/boost/python/detail/dependent.hpp b/include/boost/python/detail/dependent.hpp new file mode 100644 index 00000000..4fc48766 --- /dev/null +++ b/include/boost/python/detail/dependent.hpp @@ -0,0 +1,28 @@ +// Copyright David Abrahams 2002. 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 DEPENDENT_DWA200286_HPP +# define DEPENDENT_DWA200286_HPP + +namespace boost { namespace python { namespace detail { + +// A way to turn a concrete type T into a type dependent on U. This +// keeps conforming compilers (those implementing proper 2-phase +// name lookup for templates) from complaining about incomplete +// types in situations where it would otherwise be inconvenient or +// impossible to re-order code so that all types are defined in time. + +// One such use is when we must return an incomplete T from a member +// function template (which must be defined in the class body to +// keep MSVC happy). +template +struct dependent +{ + typedef T type; +}; + +}}} // namespace boost::python::detail + +#endif // DEPENDENT_DWA200286_HPP diff --git a/include/boost/python/detail/destroy.hpp b/include/boost/python/detail/destroy.hpp new file mode 100644 index 00000000..89e82f73 --- /dev/null +++ b/include/boost/python/detail/destroy.hpp @@ -0,0 +1,83 @@ +// Copyright David Abrahams 2002. 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 DESTROY_DWA2002221_HPP +# define DESTROY_DWA2002221_HPP + +# include +# include + +namespace boost { namespace python { namespace detail { + +template struct value_destroyer; + +template <> +struct value_destroyer +{ + template + static void execute(T const volatile* p) + { + p->T::~T(); + } +}; + +template <> +struct value_destroyer +{ + template + static void execute(A*, T const volatile* const first) + { + for (T const volatile* p = first; p != first + sizeof(A)/sizeof(T); ++p) + value_destroyer< + boost::is_array::value + ,boost::has_trivial_destructor::value + >::execute(p); + } + + template + static void execute(T const volatile* p) + { + execute(p, *p); + } +}; + +template <> +struct value_destroyer +{ + template + static void execute(T const volatile* p) + { + } +}; + +template <> +struct value_destroyer +{ + template + static void execute(T const volatile* p) + { + } +}; + +template +inline void destroy_referent_impl(void* p, T& (*)()) +{ + // note: cv-qualification needed for MSVC6 + // must come *before* T for metrowerks + value_destroyer< + (boost::is_array::value) + , (boost::has_trivial_destructor::value) + >::execute((const volatile T*)p); +} + +template +inline void destroy_referent(void* p, T(*)() = 0) +{ + destroy_referent_impl(p, (T(*)())0); +} + +}}} // namespace boost::python::detail + +#endif // DESTROY_DWA2002221_HPP diff --git a/include/boost/python/detail/exception_handler.hpp b/include/boost/python/detail/exception_handler.hpp new file mode 100644 index 00000000..9a9aa4d2 --- /dev/null +++ b/include/boost/python/detail/exception_handler.hpp @@ -0,0 +1,48 @@ +// Copyright David Abrahams 2002. 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 EXCEPTION_HANDLER_DWA2002810_HPP +# define EXCEPTION_HANDLER_DWA2002810_HPP + +# include +# include + +namespace boost { namespace python { namespace detail { + +struct BOOST_PYTHON_DECL exception_handler; + +typedef function2 const&> handler_function; + +struct BOOST_PYTHON_DECL exception_handler +{ + private: // types + + public: + explicit exception_handler(handler_function const& impl); + + inline bool handle(function0 const& f) const; + + bool operator()(function0 const& f) const; + + static exception_handler* chain; + + private: + static exception_handler* tail; + + handler_function m_impl; + exception_handler* m_next; +}; + + +inline bool exception_handler::handle(function0 const& f) const +{ + return this->m_impl(*this, f); +} + +BOOST_PYTHON_DECL void register_exception_handler(handler_function const& f); + +}}} // namespace boost::python::detail + +#endif // EXCEPTION_HANDLER_DWA2002810_HPP diff --git a/include/boost/python/detail/force_instantiate.hpp b/include/boost/python/detail/force_instantiate.hpp new file mode 100755 index 00000000..62446c32 --- /dev/null +++ b/include/boost/python/detail/force_instantiate.hpp @@ -0,0 +1,33 @@ +// Copyright David Abrahams 2002. 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 FORCE_INSTANTIATE_DWA200265_HPP +# define FORCE_INSTANTIATE_DWA200265_HPP + +namespace boost { namespace python { namespace detail { + +// Allows us to force the argument to be instantiated without +// incurring unused variable warnings + +# if !defined(BOOST_MSVC) || BOOST_MSVC == 1200 || _MSC_FULL_VER > 13102196 + +template +inline void force_instantiate(T const&) {} + +# else + +# pragma optimize("g", off) +inline void force_instantiate_impl(...) {} +# pragma optimize("", on) +template +inline void force_instantiate(T const& x) +{ + detail::force_instantiate_impl(&x); +} +# endif + +}}} // namespace boost::python::detail + +#endif // FORCE_INSTANTIATE_DWA200265_HPP diff --git a/include/boost/python/detail/indirect_traits.hpp b/include/boost/python/detail/indirect_traits.hpp new file mode 100644 index 00000000..faabecc2 --- /dev/null +++ b/include/boost/python/detail/indirect_traits.hpp @@ -0,0 +1,389 @@ +// Copyright David Abrahams 2002. 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 INDIRECT_TRAITS_DWA2002131_HPP +# define INDIRECT_TRAITS_DWA2002131_HPP +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_reference_to_const +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_const +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround +template +struct is_reference_to_const +{ + static const bool value = true; +}; +# endif + +# if 0 // Corresponding code doesn't work on MSVC yet +template +struct is_reference_to_function +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_function +{ + BOOST_STATIC_CONSTANT(bool, value = is_function::value); +}; + +template +struct is_reference_to_function +{ + BOOST_STATIC_CONSTANT(bool, value = is_function::value); +}; + +template +struct is_reference_to_function +{ + BOOST_STATIC_CONSTANT(bool, value = is_function::value); +}; + +template +struct is_reference_to_function +{ + BOOST_STATIC_CONSTANT(bool, value = is_function::value); +}; +# endif + +template +struct is_pointer_to_function +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_pointer_to_function +{ + // There's no such thing as a pointer-to-cv-function, so we don't need specializations for those + BOOST_STATIC_CONSTANT(bool, value = is_function::value); +}; + +template +struct is_reference_to_non_const +{ + BOOST_STATIC_CONSTANT( + bool, value = ( + ::boost::type_traits::ice_and< + ::boost::is_reference::value + , ::boost::type_traits::ice_not< + ::boost::python::detail::is_reference_to_const::value>::value + >::value) + ); +}; + +template +struct is_reference_to_volatile +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_volatile +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround +template +struct is_reference_to_volatile +{ + static const bool value = true; +}; +# endif + + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_pointer +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_reference_to_class +{ + BOOST_STATIC_CONSTANT( + bool, value + = (boost::type_traits::ice_and< + is_reference::value + , is_class< + typename remove_cv< + typename remove_reference::type + >::type + >::value + >::value) + ); +}; + +template +struct is_pointer_to_class +{ + BOOST_STATIC_CONSTANT( + bool, value + = (boost::type_traits::ice_and< + is_pointer::value + , is_class< + typename remove_cv< + typename remove_pointer::type + >::type + >::value + >::value) + ); +}; + +# else + +typedef char (&inner_yes_type)[3]; +typedef char (&inner_no_type)[2]; +typedef char (&outer_no_type)[1]; + +template +struct is_const_help +{ + typedef typename mpl::select_type< + is_const::value + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_volatile_help +{ + typedef typename mpl::select_type< + is_volatile::value + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_pointer_help +{ + typedef typename mpl::select_type< + is_pointer::value + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_class_help +{ + typedef typename mpl::select_type< + is_class::value + , inner_yes_type + , inner_no_type + >::type type; +}; + +# if 0 // doesn't seem to work yet +template +struct is_reference_to_function +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(::boost::detail::is_function_tester(t)) == sizeof(::boost::type_traits::yes_type)); +# endif + +template +struct is_pointer_to_function +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(::boost::detail::is_function_tester(t)) == sizeof(::boost::type_traits::yes_type)); +}; + +struct false_helper1 +{ + template + struct apply + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +}; + +template +typename is_const_help::type reference_to_const_helper(V&); +outer_no_type +reference_to_const_helper(...); + +template +struct is_reference_to_const_helper1 +{ + template + struct apply + { + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_const_helper(t)) == sizeof(inner_yes_type)); + }; +}; + +template <> +struct is_reference_to_const_helper1 : false_helper1 +{ +}; + + +template +struct is_reference_to_const + : is_reference_to_const_helper1::value>::template apply +{ +}; + + + +template +struct is_reference_to_non_const_helper1 +{ + template + struct apply + { + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_const_helper(t)) == sizeof(inner_no_type)); + }; +}; + +template <> +struct is_reference_to_non_const_helper1 : false_helper1 +{ +}; + + +template +struct is_reference_to_non_const + : is_reference_to_non_const_helper1::value>::template apply +{ +}; + + +template +typename is_volatile_help::type reference_to_volatile_helper(V&); +outer_no_type +reference_to_volatile_helper(...); + +template +struct is_reference_to_volatile_helper1 +{ + template + struct apply + { + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_volatile_helper(t)) == sizeof(inner_yes_type)); + }; +}; + +template <> +struct is_reference_to_volatile_helper1 : false_helper1 +{ +}; + + +template +struct is_reference_to_volatile + : is_reference_to_volatile_helper1::value>::template apply +{ +}; + + +template +typename is_pointer_help::type reference_to_pointer_helper(V&); +outer_no_type reference_to_pointer_helper(...); + +template +struct is_reference_to_pointer +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = (is_reference::value + && sizeof(reference_to_pointer_helper(t)) == sizeof(inner_yes_type)) + ); +}; + +template +typename is_class_help::type reference_to_class_helper(V const volatile&); +outer_no_type reference_to_class_helper(...); + +template +struct is_reference_to_class +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = (is_reference::value + && sizeof(reference_to_class_helper(t)) == sizeof(inner_yes_type)) + ); +}; + +template +typename is_class_help::type pointer_to_class_helper(V const volatile*); +outer_no_type pointer_to_class_helper(...); + +template +struct is_pointer_to_class +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = (is_pointer::value + && sizeof(pointer_to_class_helper(t)) == sizeof(inner_yes_type)) + ); +}; +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}}} // namespace boost::python::detail + +#endif // INDIRECT_TRAITS_DWA2002131_HPP diff --git a/include/boost/python/detail/make_tuple.hpp b/include/boost/python/detail/make_tuple.hpp new file mode 100644 index 00000000..41fcaa37 --- /dev/null +++ b/include/boost/python/detail/make_tuple.hpp @@ -0,0 +1,31 @@ +# // Copyright David Abrahams 2002. 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. + +#if !defined(BOOST_PP_IS_ITERATING) +# error Boost.Python - do not include this file! +#endif + +#define N BOOST_PP_ITERATION() + +#define BOOST_PYTHON_MAKE_TUPLE_ARG(z, N, ignored) \ + PyTuple_SET_ITEM( \ + result.ptr() \ + , N \ + , python::incref(python::object(a##N).ptr()) \ + ); + + template + tuple + make_tuple(BOOST_PYTHON_BINARY_ENUM(N, A, const& a)) + { + tuple result((detail::new_reference)::PyTuple_New(N)); + BOOST_PP_REPEAT(N, BOOST_PYTHON_MAKE_TUPLE_ARG, _) + return result; + } + +#undef BOOST_PYTHON_MAKE_TUPLE_ARG + +#undef N diff --git a/include/boost/python/detail/member_function_cast.hpp b/include/boost/python/detail/member_function_cast.hpp new file mode 100644 index 00000000..491e6711 --- /dev/null +++ b/include/boost/python/detail/member_function_cast.hpp @@ -0,0 +1,113 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. 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 MEMBER_FUNCTION_CAST_DWA2002311_HPP +# define MEMBER_FUNCTION_CAST_DWA2002311_HPP + +# include + +# include +# include + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +template +struct cast_helper +{ + struct yes_helper + { + static FT stage3(FT x) { return x; } + }; + + struct no_helper + { + template + static T stage3(T x) { return x; } + }; + + static yes_helper stage2(S*) { return yes_helper(); } + static no_helper stage2(void*) { return no_helper(); } +}; + +struct non_member_function_cast_impl +{ + template + static non_member_function_cast_impl stage1(T) { return non_member_function_cast_impl(); } + + template + static non_member_function_cast_impl stage2(T) { return non_member_function_cast_impl(); } + + template + T stage3(T x) { return x; } +}; + +template +struct member_function_cast_impl +{ +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + template + static non_member_function_cast_impl stage1(U) + { + return non_member_function_cast_impl(); + } +# endif + +// Member functions +# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 3, )) +# include BOOST_PP_ITERATE() +}; + +template +struct member_function_cast +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + : member_function_cast_impl +# else + : mpl::select_type< + is_member_function_pointer::value + , member_function_cast_impl + , non_member_function_cast_impl + >::type +# endif +{ +}; + +}}} // namespace boost::python::detail + +# endif // MEMBER_FUNCTION_CAST_DWA2002311_HPP + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +// outer over cv-qualifiers + +# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 +# line BOOST_PP_LINE(__LINE__, member_function_cast.hpp) +// inner over arities + +# define N BOOST_PP_ITERATION() +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + + template < + class S, class R + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_UNARY_ENUM(N, class A) + > + static cast_helper + stage1(R (S::*)(BOOST_PYTHON_UNARY_ENUM(N, A)) Q) + { + return cast_helper(); + } + +# undef N +# undef Q + +#endif diff --git a/include/boost/python/detail/module_base.hpp b/include/boost/python/detail/module_base.hpp new file mode 100644 index 00000000..144c1d93 --- /dev/null +++ b/include/boost/python/detail/module_base.hpp @@ -0,0 +1,45 @@ +// Copyright David Abrahams 2002. 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 MODULE_BASE_DWA2002227_HPP +# define MODULE_BASE_DWA2002227_HPP +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +class BOOST_PYTHON_DECL module_base +{ + public: + // Create a module. REQUIRES: only one module is created per module. + module_base(char const* name, char const* doc = 0); + ~module_base(); + + // Add elements to the module + void add(type_handle const&); // just use the type's name + + // Return a reference to the Python module object being built + inline handle<> object() const; + + protected: + void setattr_doc(const char* name, python::object const&, char const* doc); + + private: + handle<> m_module; + static PyMethodDef initial_methods[1]; +}; + +// +// inline implementations +// +inline handle<> module_base::object() const +{ + return m_module; +} + +}}} // namespace boost::python::detail + +#endif // MODULE_BASE_DWA2002227_HPP diff --git a/include/boost/python/detail/module_info.hpp b/include/boost/python/detail/module_info.hpp new file mode 100644 index 00000000..ba3f91cc --- /dev/null +++ b/include/boost/python/detail/module_info.hpp @@ -0,0 +1,51 @@ +// Copyright David Hawkes 2002. +// Permission is hereby granted to copy, use and modify this software +// for any purpose, including commercial distribution, provided this +// copyright notice is not removed. No warranty WHATSOEVER is provided with this +// software. Any user(s) accepts this software "as is" and as such they will not +// bind the author(s) to any claim of suitabilty for any purpose. + +#ifndef MODULE_INFO +# define MODULE_INFO + +#include + +namespace boost { namespace python { namespace detail { + +class module_info +{ +public: + module_info(const char *name) + { + m_module_name = name; + } + void set_module(object const& m) + { + if(!m_primary_module) + m_primary_module = m; + } + object const& get_module() const + { + return m_primary_module; + } + void set_prior_module(object const& m) + { + m_prior_module = m; + } + object const& get_prior_module() const + { + return m_prior_module; + } + const char* get_module_name() const + { + return m_module_name; + } +private: + object m_primary_module; + object m_prior_module; + const char* m_module_name; +}; + +}}} + +#endif // MODULE_INFO diff --git a/include/boost/python/detail/module_init.hpp b/include/boost/python/detail/module_init.hpp new file mode 100644 index 00000000..5b2366f6 --- /dev/null +++ b/include/boost/python/detail/module_init.hpp @@ -0,0 +1,53 @@ +// Copyright David Abrahams 2002. 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. +#ifdef BOOST_PYTHON_V2 +# error obsolete +#endif +#ifndef MODULE_INIT_DWA2002529_HPP +# define MODULE_INIT_DWA2002529_HPP + +# ifndef BOOST_PYTHON_MODULE_INIT + +# if defined(_WIN32) || defined(__CYGWIN__) + +# define BOOST_PYTHON_MODULE_INIT(name) \ +void init_module_##name(); \ +extern "C" __declspec(dllexport) void init##name() \ +{ \ + boost::python::handle_exception(&init_module_##name); \ +} \ +void init_module_##name() + +# elif defined(_AIX) + +# include +# define BOOST_PYTHON_MODULE_INIT(name) \ +void init_module_##name(); \ +extern "C" \ +{ \ + extern PyObject* _PyImport_LoadDynamicModule(char*, char*, FILE *); \ + void init##name() \ + { \ + boost::python::detail::aix_init_module(_PyImport_LoadDynamicModule, &init_module_##name); \ + } \ +} \ +void init_module_##name() + +# else + +# define BOOST_PYTHON_MODULE_INIT(name) \ +void init_module_##name(); \ +extern "C" void init##name() \ +{ \ + boost::python::handle_exception(&init_module_##name); \ +} \ +void init_module_##name() + +# endif + +# endif + +#endif // MODULE_INIT_DWA2002529_HPP diff --git a/include/boost/python/detail/preprocessor.hpp b/include/boost/python/detail/preprocessor.hpp new file mode 100644 index 00000000..89d1d26d --- /dev/null +++ b/include/boost/python/detail/preprocessor.hpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. 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 PREPROCESSOR_DWA200247_HPP +# define PREPROCESSOR_DWA200247_HPP + +# include +# include +# include +# include + +// stuff that should be in the preprocessor library + +# define BOOST_PYTHON_APPLY(x) BOOST_PP_CAT(BOOST_PYTHON_APPLY_, x) + +# define BOOST_PYTHON_APPLY_BOOST_PYTHON_ITEM(v) v +# define BOOST_PYTHON_APPLY_BOOST_PYTHON_NIL + +// cv-qualifiers + +# if !defined(__MWERKS__) || __MWERKS__ > 0x2407 +# define BOOST_PYTHON_CV_COUNT 4 +# else +# define BOOST_PYTHON_CV_COUNT 1 +# endif + +# ifndef BOOST_PYTHON_MAX_ARITY +# define BOOST_PYTHON_MAX_ARITY 15 +# endif + +# define BOOST_PYTHON_CV_QUALIFIER(i) \ + BOOST_PYTHON_APPLY( \ + BOOST_PP_TUPLE_ELEM(4, i, BOOST_PYTHON_CV_QUALIFIER_I) \ + ) + +# define BOOST_PYTHON_CV_QUALIFIER_I \ + ( \ + BOOST_PYTHON_NIL, \ + BOOST_PYTHON_ITEM(const), \ + BOOST_PYTHON_ITEM(volatile), \ + BOOST_PYTHON_ITEM(const volatile) \ + ) + +// enumerators +# define BOOST_PYTHON_UNARY_ENUM(c, text) BOOST_PP_REPEAT(c, BOOST_PYTHON_UNARY_ENUM_I, text) +# define BOOST_PYTHON_UNARY_ENUM_I(z, n, text) BOOST_PP_COMMA_IF(n) text ## n + +# define BOOST_PYTHON_BINARY_ENUM(c, a, b) BOOST_PP_REPEAT(c, BOOST_PYTHON_BINARY_ENUM_I, (a, b)) +# define BOOST_PYTHON_BINARY_ENUM_I(z, n, _) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, _), n) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, _), n) + +# define BOOST_PYTHON_ENUM_WITH_DEFAULT(c, text, def) BOOST_PP_REPEAT(c, BOOST_PYTHON_ENUM_WITH_DEFAULT_I, (text, def)) +# define BOOST_PYTHON_ENUM_WITH_DEFAULT_I(z, n, _) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, _), n) = BOOST_PP_TUPLE_ELEM(2, 1, _) + +// fixed text (no commas) +# define BOOST_PYTHON_FIXED(z, n, text) text + +// flags +# define BOOST_PYTHON_FUNCTION_POINTER 0x0001 +# define BOOST_PYTHON_POINTER_TO_MEMBER 0x0002 + +#endif // PREPROCESSOR_DWA200247_HPP diff --git a/include/boost/python/detail/python22_fixed.h b/include/boost/python/detail/python22_fixed.h new file mode 100644 index 00000000..3caff6dd --- /dev/null +++ b/include/boost/python/detail/python22_fixed.h @@ -0,0 +1,140 @@ +// Copy of Python 2.2/2.2.1 Python.h . +// Changes marked with "Boost.Python modification" +#ifndef Py_PYTHON_H +#define Py_PYTHON_H +/* Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { */ + + +/* Enable compiler features; switching on C lib defines doesn't work + here, because the symbols haven't necessarily been defined yet. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +/* Forcing SUSv2 compatibility still produces problems on some + platforms, True64 and SGI IRIX begin two of them, so for now the + define is switched off. */ +#if 0 +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 500 +#endif +#endif + +/* Include nearly all Python header files */ + +#include "patchlevel.h" +#include "pyconfig.h" + +#ifdef HAVE_LIMITS_H +#include +#endif + +/* pyconfig.h may or may not define DL_IMPORT */ +#ifndef DL_IMPORT /* declarations for DLL import/export */ +#define DL_IMPORT(RTYPE) RTYPE +#endif +#ifndef DL_EXPORT /* declarations for DLL import/export */ +#define DL_EXPORT(RTYPE) RTYPE +#endif + +#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE) +#define _SGI_MP_SOURCE +#endif + +#include +#ifndef NULL +# error "Python.h requires that stdio.h define NULL." +#endif + +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#if PY_MICRO_VERSION == 1 // Boost.Python modification: emulate Python 2.2 +#ifdef HAVE_UNISTD_H +#include +#endif +#endif // Boost.Python modification: emulate Python 2.2 + +/* CAUTION: Build setups should ensure that NDEBUG is defined on the + * compiler command line when building Python in release mode; else + * assert() calls won't be removed. + */ +#include + +#include "pyport.h" + +#include "pymem.h" + +#include "object.h" +#include "objimpl.h" + +#include "pydebug.h" + +#include "unicodeobject.h" +#include "intobject.h" +#include "longobject.h" +#include "floatobject.h" +#ifndef WITHOUT_COMPLEX +#include "complexobject.h" +#endif +#include "rangeobject.h" +#include "stringobject.h" +#include "bufferobject.h" +#include "tupleobject.h" +#include "listobject.h" +#include "dictobject.h" +#include "methodobject.h" +#include "moduleobject.h" +#include "funcobject.h" +#include "classobject.h" +#include "fileobject.h" +#include "cobject.h" +#include "traceback.h" +#include "sliceobject.h" +#include "cellobject.h" +extern "C" { // Boost.Python modification: provide missing extern "C" +#include "iterobject.h" +#include "descrobject.h" +} // Boost.Python modification: provide missing extern "C" +#include "weakrefobject.h" + +#include "codecs.h" +#include "pyerrors.h" + +#include "pystate.h" + +#include "modsupport.h" +#include "pythonrun.h" +#include "ceval.h" +#include "sysmodule.h" +#include "intrcheck.h" +#include "import.h" + +#include "abstract.h" + +#define PyArg_GetInt(v, a) PyArg_Parse((v), "i", (a)) +#define PyArg_NoArgs(v) PyArg_Parse(v, "") + +/* Convert a possibly signed character to a nonnegative int */ +/* XXX This assumes characters are 8 bits wide */ +#ifdef __CHAR_UNSIGNED__ +#define Py_CHARMASK(c) (c) +#else +#define Py_CHARMASK(c) ((c) & 0xff) +#endif + +#include "pyfpe.h" + +/* These definitions must match corresponding definitions in graminit.h. + There's code in compile.c that checks that they are the same. */ +#define Py_single_input 256 +#define Py_file_input 257 +#define Py_eval_input 258 + +#ifdef HAVE_PTH +/* GNU pth user-space thread support */ +#include +#endif +#endif /* !Py_PYTHON_H */ diff --git a/include/boost/python/detail/raw_pyobject.hpp b/include/boost/python/detail/raw_pyobject.hpp new file mode 100644 index 00000000..e9d36901 --- /dev/null +++ b/include/boost/python/detail/raw_pyobject.hpp @@ -0,0 +1,33 @@ +// Copyright David Abrahams 2002. 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 RAW_PYOBJECT_DWA2002628_HPP +# define RAW_PYOBJECT_DWA2002628_HPP + +namespace boost { namespace python { namespace detail { + +// +// Define some types which we can use to get around the vagaries of +// PyObject*. We will use these to initialize object instances, and +// keep them in namespace detail to make sure they stay out of the +// hands of users. That is much simpler than trying to grant +// friendship to all the appropriate parties. +// + +// New references are normally checked for null +struct new_reference_t; +typedef new_reference_t* new_reference; + +// Borrowed references are assumed to be non-null +struct borrowed_reference_t; +typedef borrowed_reference_t* borrowed_reference; + +// New references which aren't checked for null +struct new_non_null_reference_t; +typedef new_non_null_reference_t* new_non_null_reference; + +}}} // namespace boost::python::detail + +#endif // RAW_PYOBJECT_DWA2002628_HPP diff --git a/include/boost/python/detail/referent_storage.hpp b/include/boost/python/detail/referent_storage.hpp new file mode 100644 index 00000000..aebacf64 --- /dev/null +++ b/include/boost/python/detail/referent_storage.hpp @@ -0,0 +1,75 @@ +// Copyright David Abrahams 2002. 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 REFERENT_STORAGE_DWA200278_HPP +# define REFERENT_STORAGE_DWA200278_HPP +# include +# include + +namespace boost { namespace python { namespace detail { + +struct alignment_dummy; +typedef void (*function_ptr)(); +typedef int (alignment_dummy::*member_ptr); +typedef int (alignment_dummy::*member_function_ptr)(); + +# define BOOST_PYTHON_ALIGNER(T, n) \ + typename mpl::select_type< \ + sizeof(T) <= size, T, char>::type t##n + +// Storage for size bytes, aligned to all fundamental types no larger than size +template +union aligned_storage +{ + BOOST_PYTHON_ALIGNER(char, 0); + BOOST_PYTHON_ALIGNER(short, 1); + BOOST_PYTHON_ALIGNER(int, 2); + BOOST_PYTHON_ALIGNER(long, 3); + BOOST_PYTHON_ALIGNER(float, 4); + BOOST_PYTHON_ALIGNER(double, 5); + BOOST_PYTHON_ALIGNER(long double, 6); + BOOST_PYTHON_ALIGNER(void*, 7); + BOOST_PYTHON_ALIGNER(function_ptr, 8); + BOOST_PYTHON_ALIGNER(member_ptr, 9); + BOOST_PYTHON_ALIGNER(member_function_ptr, 10); + char bytes[size]; +}; + +# undef BOOST_PYTHON_ALIGNER + + // Compute the size of T's referent. We wouldn't need this at all, + // but sizeof() is broken in CodeWarriors <= 8.0 + template struct referent_size; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct referent_size + { + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(T)); + }; + +# else + + template struct referent_size + { + static T f(); + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(f())); + }; + +# endif + +// A metafunction returning a POD type which can store U, where T == +// U&. If T is not a reference type, returns a POD which can store T. +template +struct referent_storage +{ + typedef aligned_storage::value> type; +}; + +}}} // namespace boost::python::detail + +#endif // REFERENT_STORAGE_DWA200278_HPP diff --git a/include/boost/python/detail/result.hpp b/include/boost/python/detail/result.hpp new file mode 100755 index 00000000..84f6a554 --- /dev/null +++ b/include/boost/python/detail/result.hpp @@ -0,0 +1,124 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. 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 RESULT_DWA2002521_HPP +# define RESULT_DWA2002521_HPP + +# include + +# include + +# include +# include + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// Defines a family of overloaded function which, given x, a function +// pointer, member [function] pointer, or an AdaptableFunction object, +// returns a pointer to type*, where R is the result type of +// invoking the result of bind(x). +// +// In order to work around bugs in deficient compilers, if x might be +// an AdaptableFunction object, you must pass OL as a second argument +// to get this to work portably. + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, , BOOST_PYTHON_FUNCTION_POINTER)) +# include BOOST_PP_ITERATE() + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_CV_COUNT - 1, , BOOST_PYTHON_POINTER_TO_MEMBER)) +# include BOOST_PP_ITERATE() + +template +boost::type* result(R (T::*), int = 0) { return 0; } + +# if (defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140) \ + || (defined(__GNUC__) && __GNUC__ < 3) \ + || (defined(__MWERKS__) && __MWERKS__ < 0x3000) +// This code actually works on all implementations, but why use it when we don't have to? +template +struct get_result_type +{ + typedef boost::type type; +}; + +struct void_type +{ + typedef void type; +}; + +template +struct result_result +{ + typedef typename mpl::select_type< + is_class::value + , get_result_type + , void_type + >::type t1; + + typedef typename t1::type* type; +}; + +template +typename result_result::type +result(X const&, short) { return 0; } + +# else // Simpler code for more-capable compilers +template +boost::type* +result(X const&, short = 0) { return 0; } + +# endif + +}}} // namespace boost::python::detail + +# endif // RESULT_DWA2002521_HPP + +/* --------------- function pointers --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +# line BOOST_PP_LINE(__LINE__, result.hpp(function pointers)) + +# define N BOOST_PP_ITERATION() + +template +boost::type* result(R (*pf)(BOOST_PYTHON_UNARY_ENUM(N, A)), int = 0) +{ + return 0; +} + +# undef N + +/* --------------- pointers-to-members --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_POINTER_TO_MEMBER +// Outer over cv-qualifiers + +# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 +# line BOOST_PP_LINE(__LINE__, result.hpp(pointers-to-members)) +// Inner over arities + +# define N BOOST_PP_ITERATION() +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + +template +boost::type* result(R (T::*pmf)(BOOST_PYTHON_UNARY_ENUM(N, A)) Q, int = 0) +{ + return 0; +} + +# undef N +# undef Q + +#endif diff --git a/include/boost/python/detail/returning.hpp b/include/boost/python/detail/returning.hpp new file mode 100644 index 00000000..495a8564 --- /dev/null +++ b/include/boost/python/detail/returning.hpp @@ -0,0 +1,215 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// (C) Copyright David Abrahams 2001,2002. 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. +// +// This work was funded in part by Lawrence Berkeley National Labs +// +// This file generated for 5-argument member functions and 6-argument free +// functions by gen_returning.py + +# ifndef RETURNING_DWA20011201_HPP +# define RETURNING_DWA20011201_HPP + +# include + +# include +# include +# include +# include + +# include +# include +# include +# include +# include + +# include + +namespace boost { namespace python { namespace detail { + +# define BOOST_PYTHON_RETURNING_NON_VOID 0x0004 +# define BOOST_PYTHON_RETURNING_VOID 0x0008 + +template +struct returning +{ + // Specializations for function pointers +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, , \ + BOOST_PYTHON_FUNCTION_POINTER | BOOST_PYTHON_RETURNING_NON_VOID)) +# include BOOST_PP_ITERATE() + + // Specializations for member function pointers +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, 3, , \ + BOOST_PYTHON_POINTER_TO_MEMBER | BOOST_PYTHON_RETURNING_NON_VOID)) +# include BOOST_PP_ITERATE() +}; + +template <> +struct returning +{ + typedef void R; + // Specializations for function pointers +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, , \ + BOOST_PYTHON_FUNCTION_POINTER | BOOST_PYTHON_RETURNING_VOID)) +# include BOOST_PP_ITERATE() + + // Specializations for member function pointers +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, 3, , \ + BOOST_PYTHON_POINTER_TO_MEMBER | BOOST_PYTHON_RETURNING_VOID)) +# include BOOST_PP_ITERATE() +}; + +}}} // namespace boost::python::detail + +# undef BOOST_PYTHON_RETURNING_NON_VOID +# undef BOOST_PYTHON_RETURNING_VOID + +# endif // RETURNING_DWA20011201_HPP + +// --------------- function pointers --------------- // +#elif BOOST_PP_ITERATION_DEPTH() == 1 && (BOOST_PP_ITERATION_FLAGS() & BOOST_PYTHON_FUNCTION_POINTER) +# line BOOST_PP_LINE(__LINE__, returning.hpp(function pointers)) + +# define N BOOST_PP_ITERATION() + +# define BOOST_PYTHON_CALL_ARGS(z, n, _) \ + BOOST_PP_COMMA_IF(n) c##n(PyTuple_GET_ITEM(args_, n)) + +# define BOOST_PYTHON_CHECK_CONVERSION(z, n, _) \ + arg_from_python c##n(PyTuple_GET_ITEM(args_, n)); \ + if (!c##n.convertible()) \ + return 0; + +# if (BOOST_PP_ITERATION_FLAGS() & BOOST_PYTHON_RETURNING_NON_VOID) + + template + static PyObject* call( + R (*pf)(BOOST_PYTHON_UNARY_ENUM(N, A)) + , PyObject* args_ + , PyObject*, P const* policies) + { + // check that each of the arguments is convertible + BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + + // find the result converter + typedef typename P::result_converter result_converter; + typename mpl::apply1::type cr; + if (!cr.convertible() || !policies->precall(args_)) + return 0; + PyObject* result = cr( + (*pf)(BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)) + ); + return policies->postcall(args_, result); + } +# elif (BOOST_PP_ITERATION_FLAGS() & BOOST_PYTHON_RETURNING_VOID) + + template + static PyObject* call( + R (*pf)(BOOST_PYTHON_UNARY_ENUM(N, A)) + , PyObject* args_ + , PyObject*, P const* policies) + { + // check that each of the arguments is convertible + BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + + if (!policies->precall(args_)) + return 0; + (*pf)(BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)); + return policies->postcall(args_, detail::none()); + } +# endif // returning void / non-void + +# undef N +# undef BOOST_PYTHON_CALL_ARGS +# undef BOOST_PYTHON_CHECK_CONVERSION + +// --------------- pointers to members --------------- // +#elif BOOST_PP_ITERATION_DEPTH() == 1 && (BOOST_PP_ITERATION_FLAGS() & BOOST_PYTHON_POINTER_TO_MEMBER) + + // Outer iteration over cv-qualifications +# define BOOST_PP_ITERATION_PARAMS_2 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 && BOOST_PP_RELATIVE_FLAGS(1) & BOOST_PYTHON_POINTER_TO_MEMBER +# line BOOST_PP_LINE(__LINE__, returning.hpp(pointers-to-members)) + + // Inner iteration over arities +# define N BOOST_PP_ITERATION() +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + +# define BOOST_PYTHON_CALL_ARGS(z, n, _) \ + BOOST_PP_COMMA_IF(n) c##n(PyTuple_GET_ITEM(args_, BOOST_PP_INC(n))) + +# define BOOST_PYTHON_CHECK_CONVERSION(z, n, _) \ + arg_from_python c##n(PyTuple_GET_ITEM(args_, BOOST_PP_INC(n))); \ + if (!c##n.convertible()) \ + return 0; + +# if (BOOST_PP_RELATIVE_FLAGS(1) & BOOST_PYTHON_RETURNING_NON_VOID) + + template + static PyObject* call( + R (T::*pmf)(BOOST_PYTHON_UNARY_ENUM(N, A)) Q + , PyObject* args_ + , PyObject*, P const* policies) + { + // check that each of the arguments is convertible + // self is special + arg_from_python ct(PyTuple_GET_ITEM(args_, 0)); + if (!ct.convertible()) + return 0; + + // unroll a loop for the rest of them + BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + + // find the result converter + typedef typename P::result_converter result_converter; + typename mpl::apply1::type cr; + if (!cr.convertible() || !policies->precall(args_)) + return 0; + PyObject* result = cr( + ((ct(PyTuple_GET_ITEM(args_, 0))).*pmf)( + BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)) + ); + return policies->postcall(args_, result); + } +# elif (BOOST_PP_RELATIVE_FLAGS(1) & BOOST_PYTHON_RETURNING_VOID) + + template + static PyObject* call( + R (T::*pmf)(BOOST_PYTHON_UNARY_ENUM(N, A)) Q + , PyObject* args_ + , PyObject*, P const* policies) + { + // check that each of the arguments is convertible + // self is special + arg_from_python ct(PyTuple_GET_ITEM(args_, 0)); + if (!ct.convertible()) + return 0; + + // unroll a loop for the rest of them + BOOST_PP_REPEAT(N, BOOST_PYTHON_CHECK_CONVERSION, nil) + + if (!policies->precall(args_)) + return 0; + + ((ct(PyTuple_GET_ITEM(args_, 0))).*pmf)( + BOOST_PP_REPEAT(N, BOOST_PYTHON_CALL_ARGS, nil)); + return policies->postcall(args_, detail::none()); + } +# endif + +# undef N +# undef Q +# undef BOOST_PYTHON_CALL_ARGS +# undef BOOST_PYTHON_CHECK_CONVERSION + +#endif diff --git a/include/boost/python/detail/string_literal.hpp b/include/boost/python/detail/string_literal.hpp new file mode 100644 index 00000000..dc8b0791 --- /dev/null +++ b/include/boost/python/detail/string_literal.hpp @@ -0,0 +1,90 @@ +// Copyright David Abrahams 2002. 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 STRING_LITERAL_DWA2002629_HPP +# define STRING_LITERAL_DWA2002629_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_string_literal +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +# if !defined(__MWERKS__) || __MWERKS__ > 0x2407 +template +struct is_string_literal +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +# if (defined(__DECCXX_VER) && __DECCXX_VER <= 60590014) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730) +// This compiler mistakenly gets the type of string literals as char* +// instead of char[NN]. +template <> +struct is_string_literal +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; +# endif + +# else + +// CWPro7 has trouble with the array type deduction above +template +struct is_string_literal + : is_same +{ +}; +# endif +# else +template +struct string_literal_helper +{ + typedef char (&yes_string_literal)[1]; + typedef char (&no_string_literal)[2]; + + template + struct apply + { + typedef apply self; + static T x; + static yes_string_literal check(char const*); + static no_string_literal check(char*); + static no_string_literal check(void const volatile*); + + BOOST_STATIC_CONSTANT( + bool, value = sizeof(self::check(x)) == sizeof(yes_string_literal)); + }; +}; + +template <> +struct string_literal_helper +{ + template + struct apply + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +}; + +template +struct is_string_literal + : string_literal_helper::value>::apply +{ +}; +# endif + +}}} // namespace boost::python::detail + +#endif // STRING_LITERAL_DWA2002629_HPP diff --git a/include/boost/python/detail/target.hpp b/include/boost/python/detail/target.hpp new file mode 100644 index 00000000..bbaec740 --- /dev/null +++ b/include/boost/python/detail/target.hpp @@ -0,0 +1,75 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. 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 TARGET_DWA2002521_HPP +# define TARGET_DWA2002521_HPP + +# include + +# include + +# include +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, , BOOST_PYTHON_FUNCTION_POINTER)) +# include BOOST_PP_ITERATE() + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_CV_COUNT - 1, , BOOST_PYTHON_POINTER_TO_MEMBER)) +# include BOOST_PP_ITERATE() + +template +boost::type* target(R (T::*)) { return 0; } + +}}} // namespace boost::python::detail + +# endif // TARGET_DWA2002521_HPP + +/* --------------- function pointers --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +# line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers)) + +# define N BOOST_PP_ITERATION() + +template +boost::type* target(R (*)(BOOST_PYTHON_UNARY_ENUM(N, A))) +{ + return 0; +} + +# undef N + +/* --------------- pointers-to-members --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_POINTER_TO_MEMBER +// Outer over cv-qualifiers + +# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 +# line BOOST_PP_LINE(__LINE__, target.hpp(pointers-to-members)) +// Inner over arities + +# define N BOOST_PP_ITERATION() +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + +template +boost::type* target(R (T::*)(BOOST_PYTHON_UNARY_ENUM(N, A)) Q) +{ + return 0; +} + +# undef N +# undef Q + +#endif diff --git a/include/boost/python/detail/translate_exception.hpp b/include/boost/python/detail/translate_exception.hpp new file mode 100644 index 00000000..aa617a2a --- /dev/null +++ b/include/boost/python/detail/translate_exception.hpp @@ -0,0 +1,45 @@ +// Copyright David Abrahams 2002. 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 TRANSLATE_EXCEPTION_DWA2002810_HPP +# define TRANSLATE_EXCEPTION_DWA2002810_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +// A ternary function object used to translate C++ exceptions of type +// ExceptionType into Python exceptions by invoking an object of type +// Translate. Typically the translate function will be curried with +// boost::bind(). +template +struct translate_exception +{ + typedef typename add_reference< + typename add_const::type + >::type exception_cref; + + inline bool operator()( + exception_handler const& handler + , function0 const& f + , typename call_traits::param_type translate) const + { + try + { + return handler(f); + } + catch(exception_cref e) + { + translate(e); + return true; + } + } +}; + +}}} // namespace boost::python::detail + +#endif // TRANSLATE_EXCEPTION_DWA2002810_HPP diff --git a/include/boost/python/detail/type_list_utils.hpp b/include/boost/python/detail/type_list_utils.hpp new file mode 100644 index 00000000..d03203b9 --- /dev/null +++ b/include/boost/python/detail/type_list_utils.hpp @@ -0,0 +1,116 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002. 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. +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef TYPE_LIST_UTILS_JDG20020826_HPP +#define TYPE_LIST_UTILS_JDG20020826_HPP + +# include +# include +//# include +//# include + +# include +# include +# include +# include +# include +# include + +# include + +namespace boost { namespace python { namespace detail { + +# if (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 245) \ + && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) + + template + struct type_at : public boost::mpl::at {}; + + template + struct type_list_size : public boost::mpl::size {}; + +// template +// struct pop_front : public boost::mpl::pop_front {}; +// +// template +// struct pop_back : public boost::mpl::pop_back {}; + +# else + + template + struct type_at {}; + + template + struct type_list_size {}; + +// template +// struct pop_front {}; +// +// template +// struct pop_back {}; + +// template +// struct push_back {}; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +# endif + +}}} // namespace boost::python::detail + +#endif // TYPE_LIST_UTILS_JDG20020826_HPP + +#else // defined(BOOST_PP_IS_ITERATING) + +# define N BOOST_PP_ITERATION() + +# if (N < BOOST_PYTHON_MAX_ARITY-1) + + template + struct type_at > + { + typedef BOOST_PP_CAT(A, N) type; + }; + +// template +// struct push_back, T> +// { +// typedef boost::mpl::type_list sequence; +// }; + +# if (N > 0) + +// template +// struct pop_front > +// { +// typedef boost::mpl::type_list sequence; +// }; +// +// template +// struct pop_back > +// { +// typedef boost::mpl::type_list sequence; +// }; + +# endif +# endif + + template + struct type_list_size > + { + BOOST_STATIC_CONSTANT(long, value = N); + }; + +# undef N + +#endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/include/boost/python/detail/void_return.hpp b/include/boost/python/detail/void_return.hpp new file mode 100644 index 00000000..512aa636 --- /dev/null +++ b/include/boost/python/detail/void_return.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. 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 VOID_RETURN_DWA200274_HPP +# define VOID_RETURN_DWA200274_HPP + +# include + +namespace boost { namespace python { namespace detail { + +struct void_return +{ + void_return() {} + private: + void operator=(void_return const&); +}; + +template +struct returnable +{ + typedef T type; +}; + +# ifdef BOOST_NO_VOID_RETURNS +template <> +struct returnable +{ + typedef void_return type; +}; + +# ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> struct returnable : returnable {}; +template <> struct returnable : returnable {}; +template <> struct returnable : returnable {}; +# endif + +# endif // BOOST_NO_VOID_RETURNS + +}}} // namespace boost::python::detail + +#endif // VOID_RETURN_DWA200274_HPP diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp new file mode 100644 index 00000000..e2392bc5 --- /dev/null +++ b/include/boost/python/detail/wrap_python.hpp @@ -0,0 +1,153 @@ +// (C) Copyright David Abrahams 2000. 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. +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +// This file serves as a wrapper around which allows it to be +// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC +// behavior so that a program may be compiled in debug mode without requiring a +// special debugging build of the Python library. + + +// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the +// compiler command-line. + +// Revision History: +// 05 Mar 01 Suppress warnings under Cygwin with Python 2.0 (Dave Abrahams) +// 04 Mar 01 Rolled in some changes from the Dragon fork (Dave Abrahams) +// 01 Mar 01 define PyObject_INIT() for Python 1.x (Dave Abrahams) + +// +// Python's LongObject.h helpfully #defines ULONGLONG_MAX for us, +// which confuses Boost's config +// +#include +#ifndef ULONG_MAX +# define BOOST_PYTHON_ULONG_MAX_UNDEFINED +#endif +#ifndef LONGLONG_MAX +# define BOOST_PYTHON_LONGLONG_MAX_UNDEFINED +#endif +#ifndef ULONGLONG_MAX +# define BOOST_PYTHON_ULONGLONG_MAX_UNDEFINED +#endif + +// +// Get ahold of Python's version number +// +#include + +#ifdef _DEBUG +# ifndef BOOST_DEBUG_PYTHON +# undef _DEBUG // Don't let Python force the debug library just because we're debugging. +# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H +# endif +#endif + +// +// Some things we need in order to get Python.h to work with compilers other +// than MSVC on Win32 +// +#if defined(_WIN32) || defined(__CYGWIN__) +# if defined(__GNUC__) && defined(__CYGWIN__) + +# define SIZEOF_LONG 4 + +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2 + +typedef int pid_t; + +# define WORD_BIT 32 +# define hypot _hypot +# include + +# if PY_MAJOR_VERSION < 2 +# define HAVE_CLOCK +# define HAVE_STRFTIME +# define HAVE_STRERROR +# endif + +# define NT_THREADS + +# ifndef NETSCAPE_PI +# define USE_SOCKET +# endif + +# ifdef USE_DL_IMPORT +# define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE +# endif + +# ifdef USE_DL_EXPORT +# define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE +# define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE +# endif + +# define HAVE_LONG_LONG 1 +# define LONG_LONG long long +# endif + +# elif defined(__MWERKS__) + +# ifndef _MSC_VER +# define PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H 1 +# define _MSC_VER 900 +# endif + +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2 +# include +# else +# include +# endif +# undef hypot // undo the evil #define left by Python. + +# elif defined(__BORLANDC__) +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2 +# include +# else +# include +# endif +# undef HAVE_HYPOT +# define HAVE_HYPOT 1 +# endif + +#endif // _WIN32 + +#include + +#ifdef BOOST_PYTHON_ULONG_MAX_UNDEFINED +# undef ULONG_MAX +# undef BOOST_PYTHON_ULONG_MAX_UNDEFINED +#endif + +#ifdef BOOST_PYTHON_LONGLONG_MAX_UNDEFINED +# undef LONGLONG_MAX +# undef BOOST_PYTHON_LONGLONG_MAX_UNDEFINED +#endif + +#ifdef BOOST_PYTHON_ULONGLONG_MAX_UNDEFINED +# undef ULONGLONG_MAX +# undef BOOST_PYTHON_ULONGLONG_MAX_UNDEFINED +#endif + +#ifdef PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H +# undef _MSC_VER +#endif + +#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H +# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H +# define _DEBUG +#endif + +#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2 +# define PyObject_INIT(op, typeobj) \ + ( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) ) +#endif + +#ifdef __MWERKS__ +# pragma warn_possunwant off +#elif _MSC_VER +# pragma warning(disable:4786) +#endif diff --git a/include/boost/python/dict.hpp b/include/boost/python/dict.hpp new file mode 100644 index 00000000..b593f902 --- /dev/null +++ b/include/boost/python/dict.hpp @@ -0,0 +1,130 @@ +#ifndef DICT_20020706_HPP +#define DICT_20020706_HPP + +#include +#include +#include +#include + +namespace boost { namespace python { + +class dict : public object +{ + public: + // dict() -> new empty dictionary. + // dict(mapping) -> new dictionary initialized from a mapping object's + // (key, value) pairs. + // dict(seq) -> new dictionary initialized as if via: + BOOST_PYTHON_DECL dict(); // new dict + explicit BOOST_PYTHON_DECL dict(object_cref data); + + template + explicit dict(T const& data) + : object(dict::call(object(data))) + { + } + + // D.clear() -> None. Remove all items from D. + BOOST_PYTHON_DECL void clear(); + + // D.copy() -> a shallow copy of D + BOOST_PYTHON_DECL dict copy(); + + // D.get(k[,d]) -> D[k] if D.has_key(k), else d. d defaults to None. + BOOST_PYTHON_DECL object get(object_cref k) const; + + template + object get(T const& k) const + { + return this->get(object(k)); + } + + BOOST_PYTHON_DECL object get(object_cref k, object_cref d) const; + + template + object get(T1 const& k, T2 const& d) const + { + return this->get(object(k),object(d)); + } + + // D.has_key(k) -> 1 if D has a key k, else 0 + BOOST_PYTHON_DECL bool has_key(object_cref k) const; + + template + bool has_key(T const& k) const + { + return this->has_key(object(k)); + } + + // D.items() -> list of D's (key, value) pairs, as 2-tuples + BOOST_PYTHON_DECL list items() const; + + // D.iteritems() -> an iterator over the (key, value) items of D + BOOST_PYTHON_DECL object iteritems() const; + + // D.iterkeys() -> an iterator over the keys of D + BOOST_PYTHON_DECL object iterkeys() const; + + // D.itervalues() -> an iterator over the values of D + BOOST_PYTHON_DECL object itervalues() const; + + // D.keys() -> list of D's keys + BOOST_PYTHON_DECL list keys() const; + + // D.popitem() -> (k, v), remove and return some (key, value) pair as a + // 2-tuple; but raise KeyError if D is empty + BOOST_PYTHON_DECL tuple popitem(); + + // D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if not D.has_key(k) + BOOST_PYTHON_DECL object setdefault(object_cref k); + + template + object setdefault(T const& k) + { + return this->setdefault(object(k)); + } + + BOOST_PYTHON_DECL object setdefault(object_cref k, object_cref d); + + template + object setdefault(T1 const& k, T2 const& d) + { + return this->setdefault(object(k),object(d)); + } + + // D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k] + BOOST_PYTHON_DECL void update(object_cref E); + + template + void update(T const& E) + { + this->update(object(E)); + } + + // D.values() -> list of D's values + BOOST_PYTHON_DECL list values() const; + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dict) + + private: + static BOOST_PYTHON_DECL detail::new_reference call(object const&); +}; + + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits + : pytype_object_manager_traits<&PyDict_Type,dict> + { + }; +} + +}} // namespace boost::python + +#endif + diff --git a/include/boost/python/enum.hpp b/include/boost/python/enum.hpp new file mode 100644 index 00000000..f7d06075 --- /dev/null +++ b/include/boost/python/enum.hpp @@ -0,0 +1,76 @@ +// Copyright David Abrahams 2002. 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 ENUM_DWA200298_HPP +# define ENUM_DWA200298_HPP + +# include +# include +# include + +namespace boost { namespace python { + +template +struct enum_ : public objects::enum_base +{ + enum_(char const* name); + inline enum_& value(char const* name, T); + + private: + static PyObject* to_python(void const* x); + static void* convertible(PyObject* obj); + static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data); +}; + +template +inline enum_::enum_(char const* name) + : enum_base( + name + , &enum_::to_python + , &enum_::convertible + , &enum_::construct + , type_id()) +{ +} + +// This is the conversion function that gets registered for converting +template +PyObject* enum_::to_python(void const* x) +{ + return enum_base::to_python( + converter::registered::converters.class_object + , static_cast(*(T const*)x)); +} + +template +void* enum_::convertible(PyObject* obj) +{ + return PyObject_IsInstance( + obj + , upcast( + converter::registered::converters.class_object)) + + ? obj : 0; +} + +template +void enum_::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data) +{ + T x = static_cast(PyInt_AS_LONG(obj)); + void* const storage = ((converter::rvalue_from_python_storage*)data)->storage.bytes; + new (storage) T(x); + data->convertible = storage; +} + +template +inline enum_& enum_::value(char const* name, T x) +{ + this->add_value(name, static_cast(x)); + return *this; +} + +}} // namespace boost::python + +#endif // ENUM_DWA200298_HPP diff --git a/include/boost/python/errors.hpp b/include/boost/python/errors.hpp new file mode 100644 index 00000000..4c47aca8 --- /dev/null +++ b/include/boost/python/errors.hpp @@ -0,0 +1,57 @@ +// (C) Copyright David Abrahams 2000. 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. +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +#ifndef ERRORS_DWA052500_H_ +# define ERRORS_DWA052500_H_ + +# include +# include +# include + +namespace boost { namespace python { + +struct BOOST_PYTHON_DECL error_already_set {}; +struct BOOST_PYTHON_DECL argument_error : error_already_set {}; + +// Handles exceptions caught just before returning to Python code. +// Returns true iff an exception was caught. +BOOST_PYTHON_DECL bool handle_exception_impl(function0); + +template +bool handle_exception(T f) +{ + return handle_exception_impl(function0(boost::ref(f))); +} + +namespace detail { inline void rethrow() { throw; } } + +inline void handle_exception() +{ + handle_exception(detail::rethrow); +} + +BOOST_PYTHON_DECL void throw_argument_error(); +BOOST_PYTHON_DECL void throw_error_already_set(); + +template +inline T* expect_non_null(T* x) +{ + if (x == 0) + throw_error_already_set(); + return x; +} + +# ifdef BOOST_PYTHON_V2 +// Return source if it is an instance of pytype; throw an appropriate +// exception otherwise. +BOOST_PYTHON_DECL PyObject* pytype_check(PyTypeObject* pytype, PyObject* source); +# endif + +}} // namespace boost::python + +#endif // ERRORS_DWA052500_H_ diff --git a/include/boost/python/exception_translator.hpp b/include/boost/python/exception_translator.hpp new file mode 100644 index 00000000..830d50d2 --- /dev/null +++ b/include/boost/python/exception_translator.hpp @@ -0,0 +1,25 @@ +// Copyright David Abrahams 2002. 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 EXCEPTION_TRANSLATOR_DWA2002810_HPP +# define EXCEPTION_TRANSLATOR_DWA2002810_HPP +# include +# include +# include +# include + +namespace boost { namespace python { + +template +void register_exception_translator(Translate const& translate, boost::type* = 0) +{ + detail::register_exception_handler( + bind(detail::translate_exception(), _1, _2, translate) + ); +} + +}} // namespace boost::python + +#endif // EXCEPTION_TRANSLATOR_DWA2002810_HPP diff --git a/include/boost/python/extract.hpp b/include/boost/python/extract.hpp new file mode 100644 index 00000000..fdcaac28 --- /dev/null +++ b/include/boost/python/extract.hpp @@ -0,0 +1,240 @@ +// Copyright David Abrahams 2002. 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 EXTRACT_DWA200265_HPP +# define EXTRACT_DWA200265_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace converter +{ + template + struct extract_pointer + { + typedef Ptr result_type; + extract_pointer(PyObject*); + + bool check() const; + Ptr operator()() const; + + private: + PyObject* m_source; + void* m_result; + }; + + template + struct extract_reference + { + typedef Ref result_type; + extract_reference(PyObject*); + + bool check() const; + Ref operator()() const; + + private: + PyObject* m_source; + void* m_result; + }; + + template + struct extract_rvalue : private noncopyable + { + typedef typename call_traits::param_type result_type; + extract_rvalue(PyObject*); + + bool check() const; + result_type operator()() const; + private: + PyObject* m_source; + mutable rvalue_from_python_data m_data; + }; + + template + struct extract_object_manager + { + typedef T result_type; + extract_object_manager(PyObject*); + + bool check() const; + result_type operator()() const; + private: + PyObject* m_source; + }; + + template + struct select_extract + { + BOOST_STATIC_CONSTANT( + bool, obj_mgr = is_object_manager::value); + + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer::value); + + BOOST_STATIC_CONSTANT( + bool, ref = is_reference::value); + + typedef typename mpl::select_type< + obj_mgr + , extract_object_manager + , typename mpl::select_type< + ptr + , extract_pointer + , typename mpl::select_type< + ref + , extract_reference + , extract_rvalue + >::type + >::type + >::type type; + }; +} + +template +struct extract + : converter::select_extract::type +{ + private: + typedef typename converter::select_extract::type base; + public: + typedef typename base::result_type result_type; + + operator result_type() const + { + return (*this)(); + } + + extract(PyObject*); + extract(object const&); +}; + +// +// Implementations +// +template +inline extract::extract(PyObject* o) + : base(o) +{ +} + +template +inline extract::extract(object const& o) + : base(o.ptr()) +{ +} + +namespace converter +{ + template + inline extract_rvalue::extract_rvalue(PyObject* x) + : m_source(x) + , m_data( + (rvalue_from_python_stage1)(x, registered::converters) + ) + { + } + + template + inline bool + extract_rvalue::check() const + { + return m_data.stage1.convertible; + } + + template + inline typename extract_rvalue::result_type + extract_rvalue::operator()() const + { + return *(T*)( + // Only do the stage2 conversion once + m_data.stage1.convertible == m_data.storage.bytes + ? m_data.storage.bytes + : (rvalue_from_python_stage2)(m_source, m_data.stage1, registered::converters) + ); + } + + template + inline extract_reference::extract_reference(PyObject* obj) + : m_source(obj) + , m_result( + (get_lvalue_from_python)(obj, registered::converters) + ) + { + } + + template + inline bool extract_reference::check() const + { + return m_result != 0; + } + + template + inline Ref extract_reference::operator()() const + { + if (m_result == 0) + (throw_no_reference_from_python)(m_source, registered::converters); + + return python::detail::void_ptr_to_reference(m_result, (Ref(*)())0); + } + + template + inline extract_pointer::extract_pointer(PyObject* obj) + : m_source(obj) + , m_result( + obj == Py_None ? 0 : (get_lvalue_from_python)(obj, registered_pointee::converters) + ) + { + } + + template + inline bool extract_pointer::check() const + { + return m_source == Py_None || m_result != 0; + } + + template + inline Ptr extract_pointer::operator()() const + { + if (m_result == 0 && m_source != Py_None) + (throw_no_pointer_from_python)(m_source, registered_pointee::converters); + + return Ptr(m_result); + } + + template + inline extract_object_manager::extract_object_manager(PyObject* obj) + : m_source(obj) + { + } + + template + inline bool extract_object_manager::check() const + { + return object_manager_traits::check(m_source); + } + + template + inline T extract_object_manager::operator()() const + { + return T( + object_manager_traits::adopt(python::incref(m_source)) + ); + } +} + +}} // namespace boost::python::converter + +#endif // EXTRACT_DWA200265_HPP diff --git a/include/boost/python/handle.hpp b/include/boost/python/handle.hpp new file mode 100755 index 00000000..7fea1134 --- /dev/null +++ b/include/boost/python/handle.hpp @@ -0,0 +1,241 @@ +// Copyright David Abrahams 2002. 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 HANDLE_DWA200269_HPP +# define HANDLE_DWA200269_HPP + +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +template struct null_ok; + +template +inline null_ok* allow_null(T* p) +{ + return (null_ok*)p; +} + +namespace detail +{ + template + inline T* manage_ptr(detail::borrowed >* p, int) + { + return python::xincref((T*)p); + } + + template + inline T* manage_ptr(null_ok >* p, int) + { + return python::xincref((T*)p); + } + + template + inline T* manage_ptr(detail::borrowed* p, long) + { + return python::incref(expect_non_null((T*)p)); + } + + template + inline T* manage_ptr(null_ok* p, long) + { + return (T*)p; + } + + template + inline T* manage_ptr(T* p, ...) + { + return expect_non_null(p); + } +} + +template +class handle +{ + typedef T* (handle::* bool_type )() const; + + public: // types + typedef T element_type; + + public: // member functions + handle(); + ~handle(); + + template + explicit handle(Y* p) + : m_p( + python::upcast( + detail::manage_ptr(p, 0) + ) + ) + { + } + + handle& operator=(handle const& r); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) + + template + handle& operator=(handle const & r) // never throws + { + python::xdecref(m_p); + m_p = python::xincref(python::upcast(r.get())); + return *this; + } + +#endif + + template + handle(handle const& r) + : m_p(python::xincref(python::upcast(r.get()))) + { + } + + handle(handle const& r) + : m_p(python::xincref(r.m_p)) + { + } + + T* operator-> () const; + T& operator* () const; + T* get() const; + T* release(); + + operator bool_type() const // never throws + { + return m_p ? &handle::get : 0; + } + bool operator! () const; // never throws + + public: // implementation details -- do not touch + // Defining this in the class body suppresses a VC7 link failure + inline handle(detail::borrowed_reference x) + : m_p( + python::incref( + downcast((PyObject*)x) + )) + { + } + + private: // data members + T* m_p; +}; + +typedef handle type_handle; + +// +// Compile-time introspection +// +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +class is_handle +{ + public: + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template +class is_handle > +{ + public: + BOOST_STATIC_CONSTANT(bool, value = true); +}; +# else +namespace detail +{ + typedef char (&yes_handle_t)[1]; + typedef char (&no_handle_t)[2]; + + no_handle_t is_handle_test(...); + + template + yes_handle_t is_handle_test(boost::type< handle >); +} + +template +class is_handle +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_handle_test(boost::type())) + == sizeof(detail::yes_handle_t))); +}; +# endif + +// +// implementations +// +template +inline handle::handle() + : m_p(0) +{ +} + +template +inline handle::~handle() +{ + python::xdecref(m_p); +} + +template +inline handle& handle::operator=(handle const& r) +{ + python::xdecref(m_p); + m_p = python::xincref(r.m_p); + return *this; +} + +template +inline T* handle::operator->() const +{ + return m_p; +} + +template +inline T& handle::operator*() const +{ + return *m_p; +} + +template +inline T* handle::get() const +{ + return m_p; +} + +template +inline bool handle::operator!() const +{ + return m_p == 0; +} + +template +inline T* handle::release() +{ + T* result = m_p; + m_p = 0; + return result; +} + +// Because get_managed_object must return a non-null PyObject*, we +// return Py_None if the handle is null. +template +inline PyObject* get_managed_object(handle const& h, tag_t) +{ + return h.get() ? python::upcast(h.get()) : Py_None; +} + +}} // namespace boost::python + + +#endif // HANDLE_DWA200269_HPP diff --git a/include/boost/python/init.hpp b/include/boost/python/init.hpp new file mode 100644 index 00000000..03625a1b --- /dev/null +++ b/include/boost/python/init.hpp @@ -0,0 +1,431 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002. 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 INIT_JDG20020820_HPP +#define INIT_JDG20020820_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT \ + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT \ + ( \ + BOOST_PYTHON_MAX_ARITY, \ + class T, \ + boost::mpl::null_argument \ + ) \ + +#define BOOST_PYTHON_TEMPLATE_TYPES \ + BOOST_PP_ENUM_PARAMS \ + ( \ + BOOST_PYTHON_MAX_ARITY, \ + class T \ + ) \ + +#define BOOST_PYTHON_TEMPLATE_ARGS \ + BOOST_PP_ENUM_PARAMS \ + ( \ + BOOST_PYTHON_MAX_ARITY, \ + T \ + ) \ + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace python { + +template +struct init; // forward declaration + +/////////////////////////////////////// +template +struct optional; // forward declaration + +namespace detail { + + /////////////////////////////////////////////////////////////////////////// + // + // is_nil::value + // + // This metaprogram checks if T is nil + // + /////////////////////////////////////////////////////////////////////////// + template + struct is_nil : public boost::is_same {}; + + /////////////////////////////////////////////////////////////////////////// + // + // is_optional::value + // + // This metaprogram checks if T is an optional + // + /////////////////////////////////////////////////////////////////////////// + #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template + struct is_optional { + + private: + + template + static boost::type_traits::yes_type f(optional); + static boost::type_traits::no_type f(...); + static T t(); + + public: + + BOOST_STATIC_CONSTANT( + bool, value = + sizeof(f(t())) == sizeof(::boost::type_traits::yes_type)); + }; + + /////////////////////////////////////// + #else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template + struct is_optional { + + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template + struct is_optional > { + + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + #endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + /////////////////////////////////////////////////////////////////////////// + // + // append_to_init [ and helpers ] + // + // A metaprogram appends T to the initializer type list + // + /////////////////////////////////////////////////////////////////////////// + struct append_to_init_helper1 { + + // Case 1: default case, just push T to the back of ListT + + template + struct apply { + + typedef typename boost::mpl::push_back::sequence sequence; + }; + }; + + struct append_to_init_helper2 { + + template + struct apply { + + // Case 2: optional case, T is an optional, append all + // the contents of the optional T into back of ListT + + typedef typename boost::mpl::for_each + < + typename T::sequence, + ListT, + boost::mpl::push_back + >::state sequence; + }; + }; + + struct append_to_init_helper3 { + + // Case 3: nil case, we found a nil, do nothing + + template + struct apply { + + typedef ListT sequence; + }; + }; + + template + struct append_to_init { + + typedef typename boost::mpl::select_type + < + is_optional::value, // if + append_to_init_helper2, // then + typename boost::mpl::select_type // else + < + is_nil::value, // if + append_to_init_helper3, // then + append_to_init_helper1 // else + >::type + >::type helper; + + typedef typename helper::template apply::sequence sequence; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // check_init_params [ and helpers ] + // + // Check the init template parameters. Detect illegal + // arguments such as: + // + // init, int> // BAD trailing int + // init, optional > // BAD optional used twice + // + /////////////////////////////////////////////////////////////////////////// + template + struct check_init_params_helper { + + template + struct apply { + + // case where size of sequence is not zero + + typedef typename boost::mpl::pop_front::sequence rest; + + enum { + + // if first is optional then there must be no more + // elements to its right. if not then recurse and check + // the rest of the type list + + first_is_optional = + is_optional::type>::value, + size_of_rest = boost::mpl::size::value, + rest_is_nil = (size_of_rest == 0), + is_ok = first_is_optional ? rest_is_nil : + check_init_params_helper + ::template apply::is_ok + }; + }; + }; + + template <> + struct check_init_params_helper<0> { + + // case where size of sequence is zero + + template + struct apply { + + enum { is_ok = true }; + }; + }; + + struct init_base {}; + + template + struct check_init_params : init_base { + + typedef boost::mpl::type_list params; + + BOOST_STATIC_ASSERT + ( + check_init_params_helper::value> + ::template apply::is_ok + ); + }; + + /////////////////////////////////////////////////////////////////////////// + // + // count_optional_types [ and helpers ] + // + // count_optional_types::value computes the number of + // optional types (see init and optional below). For example: + // + // init >::value == 3 + // + /////////////////////////////////////////////////////////////////////////// + template + struct count_optionals1 { + + BOOST_STATIC_CONSTANT(int, value = 0); + }; + + template + struct count_optionals2 { + + BOOST_STATIC_CONSTANT( + int, value = boost::mpl::size::value + 1); + }; + + template + struct count_optionals + : boost::mpl::select_type + < + is_optional::value, // if + count_optionals2, // then + count_optionals1 // else + >::type + { + }; + + template + struct count_optional_types { + + BOOST_STATIC_CONSTANT(int, value = + count_optionals::value + + count_optionals::value + + count_optionals::value + ); + }; + +} // namespace detail + +/////////////////////////////////////////////////////////////////////////////// +// +// init +// +// init::sequence returns a typelist. One of T0..TN +// mat be an optional<...> see below. There should be only one +// optional in the input types and an optional should be the +// last in the list. +// +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_PYTHON_APPEND_TO_INIT(z, INDEX, D) \ + typedef typename detail::append_to_init \ + < \ + BOOST_PP_CAT(l, INDEX), \ + BOOST_PP_CAT(T, BOOST_PP_INC(INDEX)) \ + >::sequence BOOST_PP_CAT(l, BOOST_PP_INC(INDEX)); \ + + +template +struct init : detail::check_init_params +{ + typedef boost::mpl::type_list l0; + BOOST_PP_REPEAT + (BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY), BOOST_PYTHON_APPEND_TO_INIT, 0) + + typedef BOOST_PP_CAT(l, BOOST_PP_DEC(BOOST_PYTHON_MAX_ARITY)) sequence; + + BOOST_STATIC_CONSTANT(int, n_arguments = boost::mpl::size::value); + + BOOST_STATIC_CONSTANT(int, n_defaults = + (detail::count_optional_types::value) + ); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// optional +// +// optional::sequence returns a typelist. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct optional { + + typedef boost::mpl::type_list sequence; +}; + +namespace detail { + + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper::apply + // + // General case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments and recursively calls + // define_class_init_helper::apply with one less arguments (the + // rightmost argument is shaved off) + // + /////////////////////////////////////////////////////////////////////////////// + template + struct define_class_init_helper { + + template + static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc) + { + cl.def_init(args, policies, doc); + typename boost::mpl::pop_back::sequence next; + define_class_init_helper::apply(cl, policies, next, doc); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper<0>::apply + // + // Terminal case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments. + // + /////////////////////////////////////////////////////////////////////////////// + template <> + struct define_class_init_helper<0> { + + template + static void apply(ClassT& cl, CallPoliciesT const& policies, ArgsT const& args, char const* doc) + { + cl.def_init(args, policies, doc); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// define_init +// +// Accepts a class_ and an init-list. Defines a set of constructors for +// the class given the arguments. The init list (see init above) has +// n_defaults (number of default arguments and n_arguments (number of +// actual arguments). This function defines n_defaults + 1 constructors +// for the class. Each constructor after the first has one less argument +// to its right. Example: +// +// init +// +// Defines: +// +// __init__(int, char, long, double) +// __init__(int, char, long) +// __init__(int, char) +// __init__(int) +// +/////////////////////////////////////////////////////////////////////////////// +template +void +define_init(ClassT& cl, InitT const& i, CallPoliciesT const& policies, char const* doc) +{ + typedef typename InitT::sequence args_t; + detail::define_class_init_helper::apply(cl, policies, args_t(), doc); +} + +}} // namespace boost::python + +#undef BOOST_PYTHON_TEMPLATE_TYPES_WITH_DEFAULT +#undef BOOST_PYTHON_TEMPLATE_TYPES +#undef BOOST_PYTHON_TEMPLATE_ARGS +#undef BOOST_PYTHON_IS_OPTIONAL_VALUE +#undef BOOST_PYTHON_APPEND_TO_INIT + +/////////////////////////////////////////////////////////////////////////////// +#endif // INIT_JDG20020820_HPP + + + + + + + + diff --git a/include/boost/python/instance_holder.hpp b/include/boost/python/instance_holder.hpp new file mode 100755 index 00000000..28aa02e8 --- /dev/null +++ b/include/boost/python/instance_holder.hpp @@ -0,0 +1,57 @@ +// Copyright David Abrahams 2002. 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 INSTANCE_HOLDER_DWA2002517_HPP +# define INSTANCE_HOLDER_DWA2002517_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { + +// Base class for all holders +struct BOOST_PYTHON_DECL instance_holder : private noncopyable +{ + public: + instance_holder(); + virtual ~instance_holder(); + + // return the next holder in a chain + instance_holder* next() const; + + virtual void* holds(type_info) = 0; + + void install(PyObject* inst) throw(); + + // These functions should probably be located elsewhere. + + // Allocate storage for an object of the given size at the given + // offset in the Python instance<> object if bytes are available + // there. Otherwise allocate size bytes of heap memory. + static void* allocate(PyObject*, std::size_t offset, std::size_t size); + + // Deallocate storage from the heap if it was not carved out of + // the given Python object by allocate(), above. + static void deallocate(PyObject*, void* storage) throw(); + private: + instance_holder* m_next; +}; + +// This macro is needed for implementation of derived holders +# define BOOST_PYTHON_UNFORWARD(N,ignored) (typename unforward::type)(a##N) + +// +// implementation +// +inline instance_holder* instance_holder::next() const +{ + return m_next; +} + +}} // namespace boost::python + +#endif // INSTANCE_HOLDER_DWA2002517_HPP diff --git a/include/boost/python/iterator.hpp b/include/boost/python/iterator.hpp new file mode 100644 index 00000000..3f477034 --- /dev/null +++ b/include/boost/python/iterator.hpp @@ -0,0 +1,115 @@ +// Copyright David Abrahams 2002. 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 ITERATOR_DWA2002512_HPP +# define ITERATOR_DWA2002512_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + // Adds an additional layer of binding to + // objects::make_iterator(...), which allows us to pass member + // function and member data pointers. + template + inline object make_iterator( + Accessor1 get_start, Accessor2 get_finish, boost::type* target = 0, NextPolicies* = 0) + { + return objects::make_iterator_function( + boost::protect(boost::bind(get_start, _1)) + , boost::protect(boost::bind(get_finish, _1)) + ); + } + + // Guts of template class iterators<>, below. + template + struct iterators_impl + { + template + struct apply + { + typedef typename T::iterator iterator; + static iterator begin(T& x) { return x.begin(); } + static iterator end(T& x) { return x.end(); } + }; + }; + + template <> + struct iterators_impl + { + template + struct apply + { + typedef typename T::const_iterator iterator; + static iterator begin(T& x) { return x.begin(); } + static iterator end(T& x) { return x.end(); } + }; + }; +} + +// An "ordinary function generator" which contains static begin(x) and +// end(x) functions that invoke T::begin() and T::end(), respectively. +template +struct iterators + : detail::iterators_impl< + boost::is_const::value + >::template apply +{ +}; + +// Create an iterator-building function which uses the given +// accessors. Deduce the Target type from the accessors. The iterator +// returns copies of the inderlying elements. +template +object range(Accessor1 start, Accessor2 finish) +{ + return detail::make_iterator( + start, finish + , detail::target(start)); +} + +// Create an iterator-building function which uses the given accessors +// and next() policies. Deduce the Target type. +template +object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0) +{ + return detail::make_iterator(start, finish, detail::target(start)); +} + +// Create an iterator-building function which uses the given accessors +// and next() policies, operating on the given Target type +template +object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type* = 0) +{ + typedef typename add_reference::type target; + return detail::make_iterator(start, finish); +} + +// A Python callable object which produces an iterator traversing +// [x.begin(), x.end()), where x is an instance of the Container +// type. NextPolicies are used as the CallPolicies for the iterator's +// next() function. +template +struct iterator : object +{ + iterator() + : object( + python::range( + &iterators::begin, &iterators::end + )) + { + } +}; + +}} // namespace boost::python + +#endif // ITERATOR_DWA2002512_HPP diff --git a/include/boost/python/list.hpp b/include/boost/python/list.hpp new file mode 100644 index 00000000..501eeed5 --- /dev/null +++ b/include/boost/python/list.hpp @@ -0,0 +1,117 @@ +// Copyright David Abrahams 2002. 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 LIST_DWA2002627_HPP +# define LIST_DWA2002627_HPP + +# include +# include + +namespace boost { namespace python { + +class list : public object +{ + public: + BOOST_PYTHON_DECL list(); // new list + explicit BOOST_PYTHON_DECL list(object_cref sequence); // new list initialized from sequence's items + + template + explicit list(T const& sequence) + : object(list::call(object(sequence))) + { + } + + BOOST_PYTHON_DECL void append(object_cref); // append object to end + + template + void append(T const& x) + { + this->append(object(x)); + } + + BOOST_PYTHON_DECL long count(object_cref value) const; // return number of occurrences of value + + template + long count(T const& value) const + { + return this->count(object(value)); + } + + BOOST_PYTHON_DECL void extend(object_cref sequence); // extend list by appending sequence elements + + template + void extend(T const& x) + { + this->extend(object(x)); + } + + BOOST_PYTHON_DECL long index(object_cref value) const; // return index of first occurrence of value + + template + long index(T const& x) const + { + return this->index(object(x)); + } + + BOOST_PYTHON_DECL void insert(int index, object_cref); // insert object before index + BOOST_PYTHON_DECL void insert(object const& index, object_cref); + + template + void insert(int index, T const& x) // insert object before index + { + this->insert(index, object(x)); + } + + template + void insert(object const& index, T const& x) // insert object before index + { + this->insert(index, object(x)); + } + + BOOST_PYTHON_DECL object pop(); // remove and return item at index (default last) + BOOST_PYTHON_DECL object pop(long index); + BOOST_PYTHON_DECL object pop(object const& index); + + BOOST_PYTHON_DECL void remove(object_cref value); // remove first occurrence of value + + template + void remove(T const& value) + { + this->remove(object(value)); + } + + BOOST_PYTHON_DECL void reverse(); // reverse *IN PLACE* + + BOOST_PYTHON_DECL void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1 + BOOST_PYTHON_DECL void sort(object_cref cmpfunc); + + template + void sort(T const& value) + { + this->sort(object(value)); + } + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(list) + + private: + static BOOST_PYTHON_DECL detail::new_non_null_reference call(object const&); +}; + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits + : pytype_object_manager_traits<&PyList_Type,list> + { + }; +} + +}} // namespace boost::python + +#endif // LIST_DWA2002627_HPP diff --git a/include/boost/python/long.hpp b/include/boost/python/long.hpp new file mode 100644 index 00000000..3ba4f434 --- /dev/null +++ b/include/boost/python/long.hpp @@ -0,0 +1,55 @@ +// Copyright David Abrahams 2002. 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 LONG_DWA2002627_HPP +# define LONG_DWA2002627_HPP + +# include +# include + +namespace boost { namespace python { + +class long_ : public object +{ + public: + BOOST_PYTHON_DECL long_(); // new long_ + explicit BOOST_PYTHON_DECL long_(object_cref rhs); + + template + explicit long_(T const& rhs) + : object(long_::call(object(rhs))) + { + } + + explicit BOOST_PYTHON_DECL long_(object_cref rhs, object_cref base); + + template + explicit long_(T const& rhs, U const& base) + : object(long_::call(object(rhs), object(base))) + { + } + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(long_) + + private: + static BOOST_PYTHON_DECL detail::new_non_null_reference call(object const&); + static BOOST_PYTHON_DECL detail::new_non_null_reference call(object const&, object const&); +}; + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits + : pytype_object_manager_traits<&PyLong_Type,long_> + { + }; +} + +}} // namespace boost::python + +#endif // LONG_DWA2002627_HPP diff --git a/include/boost/python/make_function.hpp b/include/boost/python/make_function.hpp new file mode 100644 index 00000000..decdf5b4 --- /dev/null +++ b/include/boost/python/make_function.hpp @@ -0,0 +1,64 @@ +// 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_FUNCTION_DWA20011221_HPP +# define MAKE_FUNCTION_DWA20011221_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +template +object make_function(F f) +{ + return objects::function_object( + ::boost::bind(detail::caller(), f, _1, _2, default_call_policies()) + , detail::arg_tuple_size::value); +} + +template +object make_function(F f, Policies const& policies) +{ + return objects::function_object( + ::boost::bind(detail::caller(), f, _1, _2, policies) + , detail::arg_tuple_size::value); +} + +template +object make_constructor(HolderGenerator* = 0, ArgList* = 0) +{ + enum { nargs = mpl::size::value }; + + return objects::function_object( + ::boost::bind( + detail::caller() + , objects::make_holder + ::template apply::execute + , _1, _2, default_call_policies()) + , nargs + 1); +} + +template +object make_constructor(Policies const& policies, HolderGenerator* = 0, ArgList* = 0) +{ + enum { nargs = mpl::size::value }; + + return objects::function_object( + ::boost::bind(detail::caller(), + objects::make_holder + ::template apply::execute + , _1, _2, policies) + , nargs + 1); +} + +}} // namespace boost::python + +#endif // MAKE_FUNCTION_DWA20011221_HPP diff --git a/include/boost/python/module.hpp b/include/boost/python/module.hpp new file mode 100644 index 00000000..a455ca41 --- /dev/null +++ b/include/boost/python/module.hpp @@ -0,0 +1,109 @@ +// 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 MODULE_DWA2001128_HPP +# define MODULE_DWA2001128_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +class module : public detail::module_base +{ + public: + typedef detail::module_base base; + + module(char const* name, char const* doc = 0) + : base(name, doc) {} + + // Add elements to the module + template + module& setattr(const char* name, T const& x) + { + this->base::setattr_doc(name, python::object(x), 0); + return *this; + } + + module& add(type_handle x); // just use the type's name + + template + module& add(class_ const& c) + { + // Soon to disappear... + return *this; + } + + template + module& def(char const* name, Fn fn) + { + this->setattr_doc( + name, boost::python::make_function(fn), 0); + + return *this; + } + + template + module& def(char const* name, Arg1T arg1, Arg2T const& arg2, char const* doc = 0) + { + dispatch_def(name, arg1, arg2, doc, &arg2); + return *this; + } + + private: + + template + void + dispatch_def( + char const* name, + Fn fn, + CallPolicyOrDoc const& policy_or_doc, + char const* doc, + void const*) + { + typedef detail::def_helper helper; + + this->setattr_doc( + name, boost::python::make_function(fn, helper::get_policy(policy_or_doc)), + helper::get_doc(policy_or_doc, doc)); + } + + template + void + dispatch_def( + char const* name, + SigT sig, + StubsT const& stubs, + char const* doc, + detail::func_stubs_base const*) + { + // convert sig to a type_list (see detail::get_signature in signature.hpp) + // before calling detail::define_with_defaults. + detail::define_with_defaults( + name, stubs, default_call_policies(), + *this, detail::get_signature(sig), doc); + } +}; + +// +// inline implementations +// +inline module& module::add(type_handle x) +{ + this->base::add(x); + return *this; +} + +}} // namespace boost::python + +#endif // MODULE_DWA20011221_HPP diff --git a/include/boost/python/module_init.hpp b/include/boost/python/module_init.hpp new file mode 100644 index 00000000..1d65308a --- /dev/null +++ b/include/boost/python/module_init.hpp @@ -0,0 +1,61 @@ +// Copyright David Abrahams 2002. 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 MODULE_INIT_DWA20020722_HPP +# define MODULE_INIT_DWA20020722_HPP + +# include +# include + +# ifndef BOOST_PYTHON_MODULE_INIT + +namespace boost { namespace python { namespace detail { + +BOOST_PYTHON_DECL void init_module(char const* name, void(*)()); + +}}} + +# if defined(_WIN32) || defined(__CYGWIN__) + +# define BOOST_PYTHON_MODULE_INIT(name) \ +void init_module_##name(); \ +extern "C" __declspec(dllexport) void init##name() \ +{ \ + boost::python::detail::init_module( \ + #name,&init_module_##name); \ +} \ +void init_module_##name() + +# elif defined(_AIX) + +# include +# define BOOST_PYTHON_MODULE_INIT(name) \ +void init_module_##name(); \ +extern "C" \ +{ \ + extern PyObject* _PyImport_LoadDynamicModule(char*, char*, FILE *); \ + void init##name() \ + { \ + boost::python::detail::aix_init_module( \ + _PyImport_LoadDynamicModule, #name, &init_module_##name); \ + } \ +} \ +void init_module_##name() + +# else + +# define BOOST_PYTHON_MODULE_INIT(name) \ +void init_module_##name(); \ +extern "C" void init##name() \ +{ \ + boost::python::detail::init_module(#name, &init_module_##name); \ +} \ +void init_module_##name() + +# endif + +# endif + +#endif // MODULE_INIT_DWA20020722_HPP diff --git a/include/boost/python/object.hpp b/include/boost/python/object.hpp new file mode 100755 index 00000000..dbdb7c0a --- /dev/null +++ b/include/boost/python/object.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. 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 OBJECT_DWA2002612_HPP +# define OBJECT_DWA2002612_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + + class type_; // XXX temporary work-around + class string; + +}} // namespace boost::python + +#endif // OBJECT_DWA2002612_HPP diff --git a/include/boost/python/object/add_to_namespace.hpp b/include/boost/python/object/add_to_namespace.hpp new file mode 100644 index 00000000..6a862b3d --- /dev/null +++ b/include/boost/python/object/add_to_namespace.hpp @@ -0,0 +1,24 @@ +// Copyright David Abrahams 2002. 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 ADD_TO_NAMESPACE_DWA200286_HPP +# define ADD_TO_NAMESPACE_DWA200286_HPP + +# include + +namespace boost { namespace python { namespace objects { + +// +// A setattr that's "smart" about function overloading (and docstrings). +// +BOOST_PYTHON_DECL void add_to_namespace( + object const& name_space, char const* name, object const& attribute); + +BOOST_PYTHON_DECL void add_to_namespace( + object const& name_space, char const* name, object const& attribute, char const* doc); + +}}} // namespace boost::python::objects + +#endif // ADD_TO_NAMESPACE_DWA200286_HPP diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp new file mode 100644 index 00000000..e97f8edd --- /dev/null +++ b/include/boost/python/object/class.hpp @@ -0,0 +1,52 @@ +// 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 CLASS_DWA20011214_HPP +# define CLASS_DWA20011214_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace objects { + +struct BOOST_PYTHON_DECL class_base : python::api::object +{ + // constructor + class_base( + char const* name // The name of the class + + , std::size_t num_types // A list of class_ids. The first is the type + , type_info const*const types // this is wrapping. The rest are the types of + // any bases. + + , char const* doc = 0 // Docstring, if any. + ); + + // Retrieve the underlying object + void add_property(char const* name, object const& fget); + void add_property(char const* name, object const& fget, object const& fset); + void setattr(char const* name, object const&); + void enable_pickling(bool getstate_manages_dict); + + // Set a special attribute in the class which tells Boost.Python + // to allocate extra bytes for embedded C++ objects in Python + // instances. + void set_instance_size(std::size_t bytes); + + // Set an __init__ function which throws an appropriate exception + // for abstract classes. + void def_no_init(); +}; + +}}} // namespace boost::python::objects + +#endif // CLASS_DWA20011214_HPP diff --git a/include/boost/python/object/class_detail.hpp b/include/boost/python/object/class_detail.hpp new file mode 100644 index 00000000..f4d4d51e --- /dev/null +++ b/include/boost/python/object/class_detail.hpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2002. 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 CLASS_DETAIL_DWA200295_HPP +# define CLASS_DETAIL_DWA200295_HPP + +# include +# include + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL type_handle registered_class_object(type_info id); +BOOST_PYTHON_DECL type_handle class_metatype(); +BOOST_PYTHON_DECL type_handle class_type(); + +}}} // namespace boost::python::object + +#endif // CLASS_DETAIL_DWA200295_HPP diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp new file mode 100644 index 00000000..61364d9d --- /dev/null +++ b/include/boost/python/object/class_wrapper.hpp @@ -0,0 +1,29 @@ +// 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 CLASS_WRAPPER_DWA20011221_HPP +# define CLASS_WRAPPER_DWA20011221_HPP + +# include +# include + +namespace boost { namespace python { namespace objects { + +// Used to convert objects of type Src to wrapped C++ classes by +// building a new instance object and installing a Holder constructed +// from the Src object. +template +struct class_wrapper + : to_python_converter > +{ + static PyObject* convert(Src const& x) + { + return MakeInstance::execute(cref(x)); + } +}; + +}}} // namespace boost::python::objects + +#endif // CLASS_WRAPPER_DWA20011221_HPP diff --git a/include/boost/python/object/enum_base.hpp b/include/boost/python/object/enum_base.hpp new file mode 100644 index 00000000..37cd8f17 --- /dev/null +++ b/include/boost/python/object/enum_base.hpp @@ -0,0 +1,34 @@ +// Copyright David Abrahams 2002. 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 ENUM_BASE_DWA200298_HPP +# define ENUM_BASE_DWA200298_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +struct BOOST_PYTHON_DECL enum_base : python::api::object +{ + protected: + enum_base( + char const* name + , converter::to_python_function_t + , converter::convertible_function + , converter::constructor_function + , type_info); + + void add_value(char const* name, long value); + + static PyObject* to_python(PyTypeObject* type, long x); +}; + +}}} // namespace boost::python::object + +#endif // ENUM_BASE_DWA200298_HPP diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp new file mode 100644 index 00000000..c14f57e3 --- /dev/null +++ b/include/boost/python/object/function.hpp @@ -0,0 +1,72 @@ +// 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 FUNCTION_DWA20011214_HPP +# define FUNCTION_DWA20011214_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +struct BOOST_PYTHON_DECL function : PyObject +{ + function(py_function const&, unsigned min_args, unsigned max_args = 0); + ~function(); + + PyObject* call(PyObject*, PyObject*) const; + + // Add an attribute to the name_space with the given name. If it is + // a function object (this class), and an existing function is + // already there, add it as an overload. + static void add_to_namespace( + object const& name_space, char const* name, object const& attribute); + + static void add_to_namespace( + object const& name_space, char const* name, object const& attribute, char const* doc); + + object const& doc() const; + void doc(object const& x); + + object const& name() const; + + private: // helper functions + void argument_error(PyObject* args, PyObject* keywords) const; + void add_overload(handle const&); + + private: // data members + py_function m_fn; + unsigned m_min_args; + unsigned m_max_args; + handle m_overloads; + object m_name; + object m_doc; +}; + +// +// implementations +// +inline object const& function::doc() const +{ + return this->m_doc; +} + +inline void function::doc(object const& x) +{ + this->m_doc = x; +} + +inline object const& function::name() const +{ + return this->m_name; +} + +}}} // namespace boost::python::objects + +#endif // FUNCTION_DWA20011214_HPP diff --git a/include/boost/python/object/function_handle.hpp b/include/boost/python/object/function_handle.hpp new file mode 100644 index 00000000..f29c2e35 --- /dev/null +++ b/include/boost/python/object/function_handle.hpp @@ -0,0 +1,40 @@ +// Copyright David Abrahams 2002. 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 FUNCTION_HANDLE_DWA2002725_HPP +# define FUNCTION_HANDLE_DWA2002725_HPP +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL handle<> function_handle_impl(py_function const& f, unsigned min_args, unsigned max_args = 0); + +// Just like function_object, but returns a handle<> instead. Using +// this for arg_to_python<> allows us to break a circular dependency +// between object and arg_to_python. +template +inline handle<> function_handle(F const& f, unsigned min_args, unsigned max_args = 0) +{ + return objects::function_handle_impl(objects::py_function(f), min_args, max_args); +} + +// Just like make_function, but returns a handle<> intead. Same +// reasoning as above. +template +handle<> make_function_handle(F f) +{ + return objects::function_handle( + ::boost::bind(python::detail::caller(), f, _1, _2, default_call_policies()) + , python::detail::arg_tuple_size::value); +} + +}}} // namespace boost::python::objects + +#endif // FUNCTION_HANDLE_DWA2002725_HPP diff --git a/include/boost/python/object/function_object.hpp b/include/boost/python/object/function_object.hpp new file mode 100644 index 00000000..03535ec3 --- /dev/null +++ b/include/boost/python/object/function_object.hpp @@ -0,0 +1,24 @@ +// Copyright David Abrahams 2002. 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 FUNCTION_OBJECT_DWA2002725_HPP +# define FUNCTION_OBJECT_DWA2002725_HPP +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL api::object function_object_impl(boost::function2 const& f, unsigned min_args, unsigned max_args = 0); + +template +inline object function_object(F const& f, unsigned min_args, unsigned max_args = 0) +{ + return objects::function_object_impl(boost::function2(f), min_args, max_args); +} + +}}} // namespace boost::python::objects + +#endif // FUNCTION_OBJECT_DWA2002725_HPP diff --git a/include/boost/python/object/instance.hpp b/include/boost/python/object/instance.hpp new file mode 100644 index 00000000..94e526b2 --- /dev/null +++ b/include/boost/python/object/instance.hpp @@ -0,0 +1,50 @@ +// Copyright David Abrahams 2002. 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 INSTANCE_DWA200295_HPP +# define INSTANCE_DWA200295_HPP + +# include +# include +# include + +namespace boost { namespace python +{ + struct instance_holder; +}} // namespace boost::python + +namespace boost { namespace python { namespace objects { + +// Each extension instance will be one of these +template +struct instance +{ + PyObject_VAR_HEAD + PyObject* dict; + PyObject* weakrefs; + instance_holder* objects; + + BOOST_STATIC_CONSTANT(std::size_t, alignment = alignment_of::value); + typedef typename type_with_alignment::type align_t; + + union + { + align_t align; + char bytes[sizeof(Data)]; + } storage; +}; + +template +struct additional_instance_size +{ + typedef instance instance_data; + typedef instance instance_char; + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(instance_data) - offsetof(instance_char,storage)); +}; + +}}} // namespace boost::python::object + +#endif // INSTANCE_DWA200295_HPP diff --git a/include/boost/python/object/iterator.hpp b/include/boost/python/object/iterator.hpp new file mode 100644 index 00000000..74af64c9 --- /dev/null +++ b/include/boost/python/object/iterator.hpp @@ -0,0 +1,217 @@ +// Copyright David Abrahams 2002. 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 ITERATOR_DWA2002510_HPP +# define ITERATOR_DWA2002510_HPP + +# include +# include +# include +# 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 +// users to have to explicitly specify that the references returned by +// iterators are copied, so we just replace the result_converter from +// the default_iterator_call_policies with a permissive one which +// always copies the result. +struct default_iterator_call_policies + : default_call_policies +{ + struct result_converter + { + template + struct apply + { + typedef to_python_value type; + }; + }; +}; + +// Instantiations of these are wrapped to produce Python iterators. +template +struct iterator_range +{ + iterator_range(object sequence, Iterator start, Iterator finish); + + object m_sequence; // Keeps the sequence alive while iterating. + Iterator m_start; + Iterator m_finish; +}; + +namespace detail +{ + // Guts of the iterator's next() function. We can't just wrap an + // ordinary function because we don't neccessarily know the result + // type of dereferencing the iterator. This also saves us from + // throwing C++ exceptions to indicate end-of-sequence. + template + struct iterator_next + { + static PyObject* execute(PyObject* args_, PyObject* kw, Policies const& policies) + { + typedef iterator_range range_; + + PyObject* py_self = PyTuple_GET_ITEM(args_, 0); + arg_from_python c0(py_self); + range_* self = c0(py_self); + + // Done iterating? + if (self->m_start == self->m_finish) + { + objects::set_stop_iteration_error(); + return 0; + } + + // note: precall happens before we can check for the result + // converter in this case, to ensure it happens before the + // iterator is dereferenced. However, the arity is 1 so + // there's not much risk that this will amount to anything. + if (!policies.precall(args_)) return 0; + + PyObject* result = iterator_next::convert_result(*self->m_start); + ++self->m_start; + + return policies.postcall(args_, result); + } + private: + // Convert the result of dereferencing the iterator. Dispatched + // here because we can't neccessarily get the value_type of the + // iterator without PTS. This way, we deduce the value type by + // dereferencing. + template + static PyObject* convert_result(ValueType& x) + { + typedef typename Policies::result_converter result_converter; + typename mpl::apply1::type cr; + if (!cr.convertible()) return 0; + + return cr(x); + } + template + static PyObject* convert_result(ValueType const& x) + { + typedef typename Policies::result_converter result_converter; + typename mpl::apply1::type cr; + if (!cr.convertible()) return 0; + + return cr(x); + } + }; + + // Get a Python class which contains the given iterator and + // policies, creating it if neccessary. Requires: NextPolicies is + // default-constructible. + template + object demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies()) + { + typedef iterator_range range_; + + // Check the registry. If one is already registered, return it. + handle<> class_obj( + objects::registered_class_object(python::type_id())); + + if (class_obj.get() != 0) + return object(class_obj); + + // Make a callable object which can be used as the iterator's next() function. + object next_function = + objects::function_object( + bind(&detail::iterator_next::execute, _1, _2, policies) + , 1); + + return class_(name, no_init) + .def("__iter__", identity_function()) + .setattr("next", next_function) + ; + } + + // This class template acts as a generator for an ordinary function + // which builds a Python iterator. + template + struct make_iterator_help + { + // Extract an object x of the Target type from the first Python + // argument, and invoke get_start(x)/get_finish(x) to produce + // iterators, which are used to construct a new iterator_range<> + // object that gets wrapped into a Python iterator. + static PyObject* create( + Accessor1 const& get_start, Accessor2 const& get_finish + , PyObject* args_, PyObject* /*kw*/) + { + // Make sure the Python class is instantiated. + demand_iterator_class("iterator"); + + to_python_value > cr; + + // This check is probably redundant, since we ensure the + // type is registered above. + if (!cr.convertible()) + return 0; + + // Extract x from the first argument + PyObject* arg0 = PyTuple_GET_ITEM(args_, 0); + arg_from_python c0(arg0); + if (!c0.convertible()) return 0; + typename arg_from_python::result_type x = c0(arg0); + + // Build and convert the iterator_range<>. + return cr( + iterator_range( + object((python::detail::borrowed_reference)arg0) + , get_start(x), get_finish(x))); + } + }; +} + +// Create a Python callable object which accepts a single argument +// convertible to the C++ Target type and returns a Python +// iterator. The Python iterator uses get_start(x) and get_finish(x) +// (where x is an instance of Target) to produce begin and end +// iterators for the range, and an instance of NextPolicies is used as +// CallPolicies for the Python iterator's next() function. +template +inline object make_iterator_function( + Accessor1 const& get_start, Accessor2 const& get_finish + , boost::type* = 0, NextPolicies* = 0) +{ + typedef typename Accessor1::result_type result_type; + + return + objects::function_object( + boost::bind( + &detail::make_iterator_help< + Target,result_type,Accessor1,Accessor2,NextPolicies + >::create + , get_start, get_finish, _1, _2) + , 1 ); +} + +// +// implementation +// +template +inline iterator_range::iterator_range( + object sequence, Iterator start, Iterator finish) + : m_sequence(sequence), m_start(start), m_finish(finish) +{ +} + +}}} // namespace boost::python::objects + +#endif // ITERATOR_DWA2002510_HPP diff --git a/include/boost/python/object/iterator_core.hpp b/include/boost/python/object/iterator_core.hpp new file mode 100644 index 00000000..655fc71e --- /dev/null +++ b/include/boost/python/object/iterator_core.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2002. 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 ITERATOR_CORE_DWA2002512_HPP +# define ITERATOR_CORE_DWA2002512_HPP + +# include +# include + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL object const& identity_function(); +BOOST_PYTHON_DECL void set_stop_iteration_error(); + +}}} // namespace boost::python::object + +#endif // ITERATOR_CORE_DWA2002512_HPP diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp new file mode 100644 index 00000000..429704a3 --- /dev/null +++ b/include/boost/python/object/make_holder.hpp @@ -0,0 +1,81 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// 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_HOLDER_DWA20011215_HPP +# define MAKE_HOLDER_DWA20011215_HPP + +# include + +# include +# include +# include + +# include + +# include +# include +# include +# include + +# include + +namespace boost { namespace python { namespace objects { + +template struct make_holder; + +# define BOOST_PYTHON_FORWARD_ARG(z, index, _) \ + typedef typename mpl::at::type t##index; \ + typedef typename forward::type f##index; + +# define BOOST_PYTHON_DO_FORWARD_ARG(z, index, _) , f##index(a##index) + +// specializations... +# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FORWARD_ARG +# undef BOOST_PYTHON_DO_FORWARD_ARG + +}}} // namespace boost::python::objects + +# endif // MAKE_HOLDER_DWA20011215_HPP + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +# line BOOST_PP_LINE(__LINE__, make_holder.hpp) + +# define N BOOST_PP_ITERATION() + +template <> +struct make_holder +{ + template + struct apply + { + BOOST_PP_REPEAT(N, BOOST_PYTHON_FORWARD_ARG, nil) + static void execute( + PyObject* p + BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, t, a)) + { + typedef instance instance_t; + + void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder)); + try { + (new (memory) Holder( + p BOOST_PP_REPEAT(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p); + } + catch(...) { + Holder::deallocate(p, memory); + throw; + } + } + }; +}; + +# undef N + +#endif diff --git a/include/boost/python/object/make_instance.hpp b/include/boost/python/object/make_instance.hpp new file mode 100644 index 00000000..d5e153b9 --- /dev/null +++ b/include/boost/python/object/make_instance.hpp @@ -0,0 +1,72 @@ +// Copyright David Abrahams 2002. 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_INSTANCE_DWA200296_HPP +# define MAKE_INSTANCE_DWA200296_HPP + +# include +# include + +namespace boost { namespace python { namespace objects { + +template +struct make_instance +{ + typedef objects::instance instance_t; + + template + static PyObject* execute(Arg& x) + { + BOOST_STATIC_ASSERT(is_class::value); + PyTypeObject* type = converter::registered::converters.class_object; + + PyObject* raw_result = type->tp_alloc( + type, objects::additional_instance_size::value); + + if (raw_result != 0) + { + instance_t* result = (instance_t*)raw_result; + try + { + // construct the new C++ object and install the pointer + // in the Python object. + construct(result, x)->install(raw_result); + } + catch(...) + { + Py_DECREF(raw_result); // reclaim the Python object + throw; + } + + // Note the position of the internally-stored Holder, + // for the sake of destruction + result->ob_size = offsetof(instance_t, storage); + } + return raw_result; + } + + private: + // Kind of a hack to support code re-use. The first form is used + // to construct holders around pointers or smart pointers. The + // second form is used to construct holders around by-value + // returns. We have to pass a pointer to the owning Python object + // to the second form in order to make it forward the 2nd argument + // on to the constructor of its embedded T object. + template + static Holder* construct(instance_t* result, Arg& x) + { + return new ((void*)&result->storage) Holder(x); + } + + static Holder* construct(instance_t* result, reference_wrapper x) + { + return new ((void*)&result->storage) Holder((PyObject*)result, x); + } +}; + + +}}} // namespace boost::python::object + +#endif // MAKE_INSTANCE_DWA200296_HPP diff --git a/include/boost/python/object/pickle_support.hpp b/include/boost/python/object/pickle_support.hpp new file mode 100644 index 00000000..a5a67cc2 --- /dev/null +++ b/include/boost/python/object/pickle_support.hpp @@ -0,0 +1,123 @@ +// (C) Copyright R.W. Grosse-Kunstleve 2002. +// 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 BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP +#define BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP + +namespace boost { namespace python { + +namespace api +{ + class object; +} +using api::object; +class tuple; + +BOOST_PYTHON_DECL object const& make_instance_reduce_function(); + +struct pickle_suite; + +namespace error_messages { + + template + struct missing_pickle_suite_function_or_incorrect_signature {}; + + inline void must_be_derived_from_pickle_suite(pickle_suite const&) {} +} + +namespace detail { struct pickle_suite_registration; } + +struct pickle_suite +{ + private: + struct inaccessible {}; + friend struct detail::pickle_suite_registration; + public: + static inaccessible* getinitargs() { return 0; } + static inaccessible* getstate() { return 0; } + static inaccessible* setstate() { return 0; } + static bool getstate_manages_dict() { return false; } +}; + +namespace detail { + + struct pickle_suite_registration + { + typedef pickle_suite::inaccessible inaccessible; + + template + static + void + register_( + Class_& cl, + tuple (*getinitargs_fn)(Tgetinitargs), + inaccessible* (*getstate_fn)(), + inaccessible* (*setstate_fn)(), + bool) + { + cl.enable_pickling(false); + cl.def("__getinitargs__", getinitargs_fn); + } + + template + static + void + register_( + Class_& cl, + inaccessible* (*getinitargs_fn)(), + Rgetstate (*getstate_fn)(Tgetstate), + void (*setstate_fn)(Tsetstate, Ttuple), + bool getstate_manages_dict) + { + cl.enable_pickling(getstate_manages_dict); + cl.def("__getstate__", getstate_fn); + cl.def("__setstate__", setstate_fn); + } + + template + static + void + register_( + Class_& cl, + tuple (*getinitargs_fn)(Tgetinitargs), + Rgetstate (*getstate_fn)(Tgetstate), + void (*setstate_fn)(Tsetstate, Ttuple), + bool getstate_manages_dict) + { + cl.enable_pickling(getstate_manages_dict); + cl.def("__getinitargs__", getinitargs_fn); + cl.def("__getstate__", getstate_fn); + cl.def("__setstate__", setstate_fn); + } + + template + static + void + register_( + Class_&, + ...) + { + typedef typename + error_messages::missing_pickle_suite_function_or_incorrect_signature< + Class_>::error_type error_type; + } + }; + + template + struct pickle_suite_finalize + : PickleSuiteType, + pickle_suite_registration + {}; + +} // namespace detail + +}} // namespace boost::python + +#endif // BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp new file mode 100644 index 00000000..9ead5d94 --- /dev/null +++ b/include/boost/python/object/pointer_holder.hpp @@ -0,0 +1,158 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// 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 POINTER_HOLDER_DWA20011215_HPP +# define POINTER_HOLDER_DWA20011215_HPP + +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include + +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward::type)(a##n) + +template +struct pointer_holder : instance_holder +{ + typedef Value value_type; + + pointer_holder(Pointer); + + // Forward construction to the held object + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, , 1)) +# include BOOST_PP_ITERATE() + + private: // types + + private: // required holder implementation + void* holds(type_info); + + private: // data members + Pointer m_p; +}; + +template +struct pointer_holder_back_reference : instance_holder +{ + private: + typedef typename python::pointee::type held_type; + public: + typedef Value value_type; + + // Not sure about this one -- can it work? The source object + // undoubtedly does not carry the correct back reference pointer. + pointer_holder_back_reference(Pointer); + + // Forward construction to the held object +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, , 2)) +# include BOOST_PP_ITERATE() + + private: // required holder implementation + void* holds(type_info); + + private: // data members + Pointer m_p; +}; + +# undef BOOST_PYTHON_UNFORWARD_LOCAL + +template +inline pointer_holder::pointer_holder(Pointer p) + : m_p(p) +{ +} + +template +inline pointer_holder_back_reference::pointer_holder_back_reference(Pointer p) + : m_p(p) +{ +} + +template +void* pointer_holder::holds(type_info dst_t) +{ + if (dst_t == python::type_id()) + return &this->m_p; + + type_info src_t = python::type_id(); + return src_t == dst_t ? &*this->m_p + : find_dynamic_type(&*this->m_p, src_t, dst_t); +} + +template +void* pointer_holder_back_reference::holds(type_info dst_t) +{ + if (dst_t == python::type_id()) + return &this->m_p; + + if (dst_t == python::type_id()) + return &*this->m_p; + + type_info src_t = python::type_id(); + Value* p = &*this->m_p; + return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t); +} + +}}} // namespace boost::python::objects + +# endif // POINTER_HOLDER_DWA20011215_HPP + +/* --------------- pointer_holder --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 +# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp) + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template< BOOST_PYTHON_UNARY_ENUM(N, class A) > +# endif + pointer_holder(PyObject* BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) + : m_p(new Value( + BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + )) + {} + +# undef N + +/* --------------- pointer_holder_back_reference --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2 +# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp(pointer_holder_back_reference)) + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template < BOOST_PYTHON_UNARY_ENUM(N, class A) > +# endif + pointer_holder_back_reference( + PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) + : m_p(new held_type( + p BOOST_PP_COMMA_IF(N) BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + )) + {} + +# undef N + +#endif diff --git a/include/boost/python/object/py_function.hpp b/include/boost/python/object/py_function.hpp new file mode 100644 index 00000000..0682d692 --- /dev/null +++ b/include/boost/python/object/py_function.hpp @@ -0,0 +1,22 @@ +// Copyright David Abrahams 2002. 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 PY_FUNCTION_DWA200286_HPP +# define PY_FUNCTION_DWA200286_HPP +# include + +namespace boost { namespace python { namespace objects { + +// This type is used as a "generalized Python callback", wrapping the +// function signature: +// +// PyObject* (PyObject* args, PyObject* keywords) +// +// We use boost::function to avoid generating lots of virtual tables +typedef boost::function2 py_function; + +}}} // namespace boost::python::objects + +#endif // PY_FUNCTION_DWA200286_HPP diff --git a/include/boost/python/object/select_holder.hpp b/include/boost/python/object/select_holder.hpp new file mode 100644 index 00000000..6902f68d --- /dev/null +++ b/include/boost/python/object/select_holder.hpp @@ -0,0 +1,148 @@ +// Copyright David Abrahams 2002. 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 SELECT_HOLDER_DWA2002322_HPP +# define SELECT_HOLDER_DWA2002322_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +namespace detail +{ + template + struct select_value_holder + { + BOOST_STATIC_CONSTANT(bool, selector = (!is_same::value) | has_back_reference::value); + + typedef typename mpl::select_type< + selector + , value_holder_back_reference + , value_holder + >::type type; + + static inline void register_() + { + select_value_holder::register_(mpl::bool_t()); + } + + static type* get() { return 0; } + + private: + static inline void register_(mpl::bool_t) + { + python::detail::force_instantiate(instance_finder::registration); + } + + static inline void register_(mpl::bool_t) + { + } + }; + + template + struct select_pointer_holder + { + typedef typename python::pointee::type pointee; + BOOST_STATIC_CONSTANT(bool, selector = (!is_same::value) | has_back_reference::value); + + typedef typename mpl::select_type< + selector + , pointer_holder_back_reference + , pointer_holder + >::type type; + + static inline void register_() + { + select_pointer_holder::register_(mpl::bool_t()); + } + + static type* get() { return 0; } + + private: + static inline void register_(mpl::bool_t) + { + // not implemented at least until we solve the back + // reference issue mentioned in pointer_holder.hpp. + // + // python::detail::force_instantiate( + // class_wrapper >()); + + python::detail::force_instantiate(instance_finder::registration); + python::detail::force_instantiate(instance_finder::registration); + } + + struct construct_from_pointer + { + static type* execute(PyObject*, Ptr x) + { + return new type(x); + } + }; + + static inline void register_(mpl::bool_t) + { + python::detail::force_instantiate( + objects::class_wrapper< + Ptr + , type + , make_instance >()); + + python::detail::force_instantiate( + instance_finder::registration); + } + }; +} + +template +struct select_holder +{ + static inline std::size_t additional_size() + { + return additional_size_helper(execute((Held*)0)); + } + + static inline detail::select_value_holder + execute(python::detail::not_specified*) + { + return detail::select_value_holder(); + } + + static inline detail::select_value_holder + execute(T*) + { + return detail::select_value_holder(); + } + + static inline detail::select_pointer_holder + execute(void*) + { + return detail::select_pointer_holder(); + } + + private: + template + static inline std::size_t additional_size_helper(Selector const&) + { + typedef typename Selector::type holder; + return additional_instance_size::value; + } +}; + +}}} // namespace boost::python::objects + +#endif // SELECT_HOLDER_DWA2002322_HPP diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp new file mode 100644 index 00000000..ea751edc --- /dev/null +++ b/include/boost/python/object/value_holder.hpp @@ -0,0 +1,131 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// 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 VALUE_HOLDER_DWA20011215_HPP +# define VALUE_HOLDER_DWA20011215_HPP + +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward::type)(a##n) + +template +struct value_holder : instance_holder +{ + typedef Held value_type; + + // Forward construction to the held object +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, , 1)) +# include BOOST_PP_ITERATE() + + private: // required holder implementation + void* holds(type_info); + + private: // data members + Held m_held; +}; + +template +struct value_holder_back_reference : instance_holder +{ + typedef Held value_type; + + // Forward construction to the held object +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, , 2)) +# include BOOST_PP_ITERATE() + +private: // required holder implementation + void* holds(type_info); + + private: // data members + BackReferenceType m_held; +}; + +# undef BOOST_PYTHON_UNFORWARD_LOCAL + +template +void* value_holder::holds(type_info dst_t) +{ + type_info src_t = python::type_id(); + return src_t == dst_t ? &m_held + : find_static_type(&m_held, src_t, dst_t); +} + +template +void* value_holder_back_reference::holds( + type_info dst_t) +{ + type_info src_t = python::type_id(); + Held* x = &m_held; + + if (dst_t == src_t) + return x; + else if (dst_t == python::type_id()) + return &m_held; + else + return find_static_type(x, src_t, dst_t); +} + +}}} // namespace boost::python::objects + +# endif // VALUE_HOLDER_DWA20011215_HPP + +// --------------- value_holder --------------- + +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 +# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder)) + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template +# endif + value_holder( + PyObject* BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) + : m_held( + BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + ) + {} + +# undef N + +// --------------- value_holder_back_reference --------------- + +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2 +# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder_back_reference)) + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template +# endif + value_holder_back_reference( + PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, a)) + : m_held( + p BOOST_PP_COMMA_IF(N) + BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + ) + { + } + +# undef N + +#endif diff --git a/include/boost/python/object_call.hpp b/include/boost/python/object_call.hpp new file mode 100644 index 00000000..31b2eff9 --- /dev/null +++ b/include/boost/python/object_call.hpp @@ -0,0 +1,22 @@ +# // Copyright David Abrahams 2002. 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. + +#if !defined(BOOST_PP_IS_ITERATING) +# error Boost.Python - do not include this file! +#endif + +#define N BOOST_PP_ITERATION() + + template + typename detail::dependent::type + operator()(BOOST_PYTHON_BINARY_ENUM(N, A, const& a)) const + { + typedef typename detail::dependent::type obj; + U const& self = *static_cast(this); + return call(get_managed_object(self, tag), BOOST_PYTHON_UNARY_ENUM(N, a)); + } + +#undef N diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp new file mode 100755 index 00000000..a0119503 --- /dev/null +++ b/include/boost/python/object_core.hpp @@ -0,0 +1,386 @@ +// Copyright David Abrahams 2002. 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 OBJECT_CORE_DWA2002615_HPP +# define OBJECT_CORE_DWA2002615_HPP + +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include + +namespace boost { namespace python { + +namespace converter +{ + template struct arg_to_python; +} + +// Put this in an inner namespace so that the generalized operators won't take over +namespace api +{ + +// This file contains the definition of the object class and enough to +// construct/copy it, but not enough to do operations like +// attribute/item access or addition. + + template class proxy; + + struct const_attribute_policies; + struct attribute_policies; + struct const_item_policies; + struct item_policies; + struct const_slice_policies; + struct slice_policies; + + typedef proxy const_object_attribute; + typedef proxy object_attribute; + typedef proxy const_object_item; + typedef proxy object_item; + typedef proxy const_object_slice; + typedef proxy object_slice; + + // + // is_proxy -- proxy type detection + // +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_proxy + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + template + struct is_proxy > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +# else + typedef char yes_proxy; + typedef char (&no_proxy)[2]; + template + yes_proxy is_proxy_helper(boost::type >*); + no_proxy is_proxy_helper(...); + template + struct is_proxy + { + BOOST_STATIC_CONSTANT( + bool, value = (sizeof(is_proxy_helper((boost::type*)0)) + == sizeof(yes_proxy))); + }; +# endif + + template struct object_initializer; + + class object; + typedef PyObject* (object::*bool_type)() const; + + template + class object_operators + { + protected: +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 + typedef object const& object_cref; +# else + typedef object object_cref; +# endif + public: + // function call + // + object operator()() const; + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + + // truth value testing + // + operator bool_type() const; + bool operator!() const; // needed for vc6 + + // Attribute access + // + const_object_attribute attr(char const*) const; + object_attribute attr(char const*); + + // item access + // + const_object_item operator[](object_cref) const; + object_item operator[](object_cref); + + template + const_object_item + operator[](T const& key) const +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return (*this)[object(key)]; + } +# endif + + template + object_item + operator[](T const& key) +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return (*this)[object(key)]; + } +# endif + + // slicing + // + const_object_slice slice(object_cref, object_cref) const; + object_slice slice(object_cref, object_cref); + + const_object_slice slice(slice_nil, object_cref) const; + object_slice slice(slice_nil, object_cref); + + const_object_slice slice(object_cref, slice_nil) const; + object_slice slice(object_cref, slice_nil); + + template + const_object_slice + slice(T const& start, V const& end) const +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return this->slice( + slice_bound::type(start) + , slice_bound::type(end)); + } +# endif + + template + object_slice + slice(T const& start, V const& end) +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return this->slice( + slice_bound::type(start) + , slice_bound::type(end)); + } +# endif + private: + // there is a confirmed CWPro8 codegen bug here. We prevent the + // early destruction of a temporary by binding a named object + // instead. +# if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3001 + typedef object const& object_cref2; +# else + typedef object const object_cref2; +# endif + }; + + // VC6 and VC7 require this base class in order to generate the + // correct copy constructor for object. We can't define it there + // explicitly or it will complain of ambiguity. + struct object_base : object_operators + { + // copy constructor without NULL checking, for efficiency. + inline object_base(object_base const&); + inline object_base(PyObject* ptr); + + object_base& operator=(object_base const& rhs); + ~object_base(); + + // Underlying object access -- returns a borrowed reference + PyObject* ptr() const; + + private: + PyObject* m_ptr; + }; + + class object : public object_base + { + public: + // default constructor creates a None object + object(); + // explicit conversion from any C++ object to Python + template + explicit object(T const& x) + : object_base( + object_initializer< + is_proxy::value + , converter::is_object_manager::value + >::get(&x, detail::convertible::check(&x))) + { + } + + // Throw error_already_set() if the handle is null. + BOOST_PYTHON_DECL explicit object(handle<> const&); + + public: // implementation detail -- for internal use only + explicit object(detail::borrowed_reference); + explicit object(detail::new_reference); + explicit object(detail::new_non_null_reference); + }; + + // Macros for forwarding constructors in classes derived from + // object. Derived classes will usually want these as an + // implementation detail +# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_(derived) \ + inline explicit derived(python::detail::borrowed_reference p) \ + : object(p) {} \ + inline explicit derived(python::detail::new_reference p) \ + : object(p) {} \ + inline explicit derived(python::detail::new_non_null_reference p) \ + : object(p) {} + +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 +# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_ +# else + // MSVC6 has a bug which causes an explicit template constructor to + // be preferred over an appropriate implicit conversion operator + // declared on the argument type. Normally, that would cause a + // runtime failure when using extract to extract a type with a + // templated constructor. This additional constructor will turn that + // runtime failure into an ambiguity error at compile-time due to + // the lack of partial ordering, or at least a link-time error if no + // generalized template constructor is declared. +# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(derived) \ + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_(derived) \ + template \ + explicit derived(extract const&); +# endif + + // + // object_initializer -- get the handle to construct the object with, + // based on whether T is a proxy or derived from object + // + template + struct object_initializer + { + static PyObject* + get(object const* x, detail::yes_convertible) + { + return python::incref(x->ptr()); + } + + template + static PyObject* + get(T const* x, detail::no_convertible) + { + return python::incref(converter::arg_to_python(*x).get()); + } + }; + + template <> + struct object_initializer + { + template + static PyObject* + get(proxy const* x, detail::no_convertible) + { + return python::incref(x->operator object().ptr()); + } + }; + + template <> + struct object_initializer + { + template + static PyObject* + get(T const* x, ...) + { + return python::incref(get_managed_object(*x, tag)); + } + }; + + template <> + struct object_initializer + {}; // empty implementation should cause an error +} +using api::object; +template struct extract; + +// +// implementation +// + +inline object::object() + : object_base(python::incref(Py_None)) +{} + +// copy constructor without NULL checking, for efficiency +inline api::object_base::object_base(object_base const& rhs) + : m_ptr(python::incref(rhs.m_ptr)) +{} + +inline api::object_base::object_base(PyObject* p) + : m_ptr(p) +{} + +inline api::object_base& api::object_base::operator=(api::object_base const& rhs) +{ + Py_INCREF(rhs.m_ptr); + Py_DECREF(this->m_ptr); + this->m_ptr = rhs.m_ptr; + return *this; +} + +inline api::object_base::~object_base() +{ + Py_DECREF(m_ptr); +} + +inline object::object(detail::borrowed_reference p) + : object_base(python::incref((PyObject*)p)) +{} + +inline object::object(detail::new_reference p) + : object_base(expect_non_null((PyObject*)p)) +{} + +inline object::object(detail::new_non_null_reference p) + : object_base((PyObject*)p) +{} + +inline PyObject* api::object_base::ptr() const +{ + return m_ptr; +} + +// +// Converter specialization implementations +// +namespace converter +{ + template struct object_manager_traits; + + template <> + struct object_manager_traits + { + BOOST_STATIC_CONSTANT(bool, is_specialized = true); + static bool check(PyObject*) { return true; } + + static python::detail::new_non_null_reference adopt(PyObject* x) + { + return python::detail::new_non_null_reference(x); + } + }; +} + +inline PyObject* get_managed_object(object const& x, tag_t) +{ + return x.ptr(); +} + +}} // namespace boost::python + +#endif // OBJECT_CORE_DWA2002615_HPP diff --git a/include/boost/python/object_fwd.hpp b/include/boost/python/object_fwd.hpp new file mode 100644 index 00000000..8b0c093e --- /dev/null +++ b/include/boost/python/object_fwd.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2002. 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 OBJECT_FWD_DWA2002724_HPP +# define OBJECT_FWD_DWA2002724_HPP + +namespace boost { namespace python { +namespace api +{ + class object; +} +using api::object; +}} // namespace boost::python + +#endif // OBJECT_FWD_DWA2002724_HPP diff --git a/include/boost/python/object_operators.hpp b/include/boost/python/object_operators.hpp new file mode 100644 index 00000000..fb14d484 --- /dev/null +++ b/include/boost/python/object_operators.hpp @@ -0,0 +1,94 @@ +// Copyright David Abrahams 2002. 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 OBJECT_OPERATORS_DWA2002617_HPP +# define OBJECT_OPERATORS_DWA2002617_HPP + +# include +# include + +namespace boost { namespace python { namespace api { + +template +object object_operators::operator()() const +{ + object_cref2 f = *static_cast(this); + return call(f.ptr()); +} + + +template +inline +object_operators::operator bool_type() const +{ + object_cref2 x = *static_cast(this); + return PyObject_IsTrue(x.ptr()) ? &object::ptr : 0; +} + +template +inline bool +object_operators::operator!() const +{ + object_cref2 x = *static_cast(this); + return !PyObject_IsTrue(x.ptr()); +} + +# define BOOST_PYTHON_COMPARE_OP(op, opid) \ +template \ +bool operator op(L const& l, R const& r) \ +{ \ + return PyObject_RichCompareBool( \ + object(l).ptr(), object(r).ptr(), opid); \ +} +BOOST_PYTHON_COMPARE_OP(>, Py_GT) +BOOST_PYTHON_COMPARE_OP(>=, Py_GE) +BOOST_PYTHON_COMPARE_OP(<, Py_LT) +BOOST_PYTHON_COMPARE_OP(<=, Py_LE) +BOOST_PYTHON_COMPARE_OP(==, Py_EQ) +BOOST_PYTHON_COMPARE_OP(!=, Py_NE) +# undef BOOST_PYTHON_COMPARE_OP + +# define BOOST_PYTHON_BINARY_OPERATOR(op) \ +BOOST_PYTHON_DECL object operator op(object const& l, object const& r); \ +template \ +object operator op(L const& l, R const& r) \ +{ \ + return object(l) op object(r); \ +} +BOOST_PYTHON_BINARY_OPERATOR(+) +BOOST_PYTHON_BINARY_OPERATOR(-) +BOOST_PYTHON_BINARY_OPERATOR(*) +BOOST_PYTHON_BINARY_OPERATOR(/) +BOOST_PYTHON_BINARY_OPERATOR(%) +BOOST_PYTHON_BINARY_OPERATOR(<<) +BOOST_PYTHON_BINARY_OPERATOR(>>) +BOOST_PYTHON_BINARY_OPERATOR(&) +BOOST_PYTHON_BINARY_OPERATOR(^) +BOOST_PYTHON_BINARY_OPERATOR(|) +# undef BOOST_PYTHON_BINARY_OPERATOR + + +# define BOOST_PYTHON_INPLACE_OPERATOR(op) \ +BOOST_PYTHON_DECL object& operator op(object& l, object const& r); \ +template \ +object& operator op(object& l, R const& r) \ +{ \ + return l op object(r); \ +} +BOOST_PYTHON_INPLACE_OPERATOR(+=) +BOOST_PYTHON_INPLACE_OPERATOR(-=) +BOOST_PYTHON_INPLACE_OPERATOR(*=) +BOOST_PYTHON_INPLACE_OPERATOR(/=) +BOOST_PYTHON_INPLACE_OPERATOR(%=) +BOOST_PYTHON_INPLACE_OPERATOR(<<=) +BOOST_PYTHON_INPLACE_OPERATOR(>>=) +BOOST_PYTHON_INPLACE_OPERATOR(&=) +BOOST_PYTHON_INPLACE_OPERATOR(^=) +BOOST_PYTHON_INPLACE_OPERATOR(|=) +# undef BOOST_PYTHON_INPLACE_OPERATOR + +}}} // namespace boost::python + +#endif // OBJECT_OPERATORS_DWA2002617_HPP diff --git a/include/boost/python/object_protocol.hpp b/include/boost/python/object_protocol.hpp new file mode 100755 index 00000000..975c9379 --- /dev/null +++ b/include/boost/python/object_protocol.hpp @@ -0,0 +1,80 @@ +// Copyright David Abrahams 2002. 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 OBJECT_PROTOCOL_DWA2002615_HPP +# define OBJECT_PROTOCOL_DWA2002615_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { namespace api { + +template +object getattr(Target const& target, Key const& key) +{ + return getattr(object(target), object(key)); +} + +template +object getattr(Target const& target, Key const& key, Default const& default_) +{ + return getattr(object(target), object(key), object(default_)); +} + + +template +void setattr(object const& target, Key const& key, Value const& value) +{ + return setattr(target, object(key), object(value)); +} + +template +void delattr(object const& target, Key const& key) +{ + delattr(target, object(key)); +} + +template +object getitem(Target const& target, Key const& key) +{ + return getitem(object(target), object(key)); +} + + +template +void setitem(object const& target, Key const& key, Value const& value) +{ + return setitem(target, object(key), object(value)); +} + +template +void delitem(object const& target, Key const& key) +{ + delitem(target, object(key)); +} + +template +object getslice(Target const& target, Begin const& begin, End const& end) +{ + return getslice(object(target), object(begin), object(end)); +} + +template +void setslice(object const& target, Begin const& begin, End const& end, Value const& value) +{ + return setslice(target, object(begin), object(end), object(value)); +} + +template +void delslice(object const& target, Begin const& begin, End const& end) +{ + delslice(target, object(begin), object(end)); +} + +}}} // namespace boost::python::api + +#endif // OBJECT_PROTOCOL_DWA2002615_HPP diff --git a/include/boost/python/object_protocol_core.hpp b/include/boost/python/object_protocol_core.hpp new file mode 100755 index 00000000..c5c41c6a --- /dev/null +++ b/include/boost/python/object_protocol_core.hpp @@ -0,0 +1,52 @@ +// Copyright David Abrahams 2002. 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 OBJECT_PROTOCOL_CORE_DWA2002615_HPP +# define OBJECT_PROTOCOL_CORE_DWA2002615_HPP + +# include + +namespace boost { namespace python { + +namespace api +{ + class object; + + BOOST_PYTHON_DECL object getattr(object const& target, object const& key); + BOOST_PYTHON_DECL object getattr(object const& target, object const& key, object const& default_); + BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value); + BOOST_PYTHON_DECL void delattr(object const& target, object const& key); + + // These are defined for efficiency, since attributes are commonly + // accessed through literal strings. + BOOST_PYTHON_DECL object getattr(object const& target, char const* key); + BOOST_PYTHON_DECL object getattr(object const& target, char const* key, object const& default_); + BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value); + BOOST_PYTHON_DECL void delattr(object const& target, char const* key); + + BOOST_PYTHON_DECL object getitem(object const& target, object const& key); + BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value); + BOOST_PYTHON_DECL void delitem(object const& target, object const& key); + + BOOST_PYTHON_DECL object getslice(object const& target, handle<> const& begin, handle<> const& end); + BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, handle<> const& end, object const& value); + BOOST_PYTHON_DECL void delslice(object const& target, handle<> const& begin, handle<> const& end); +} + +using api::getattr; +using api::setattr; +using api::delattr; + +using api::getitem; +using api::setitem; +using api::delitem; + +using api::getslice; +using api::setslice; +using api::delslice; + +}} // namespace boost::python + +#endif // OBJECT_PROTOCOL_CORE_DWA2002615_HPP diff --git a/include/boost/python/object_slices.hpp b/include/boost/python/object_slices.hpp new file mode 100644 index 00000000..eb8dcb0b --- /dev/null +++ b/include/boost/python/object_slices.hpp @@ -0,0 +1,125 @@ +// Copyright David Abrahams 2002. 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 OBJECT_SLICES_DWA2002615_HPP +# define OBJECT_SLICES_DWA2002615_HPP + +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace api { + +struct const_slice_policies +{ + typedef std::pair, handle<> > key_type; + static object get(object const& target, key_type const& key); +}; + +struct slice_policies : const_slice_policies +{ + static object const& set(object const& target, key_type const& key, object const& value); + static void del(object const& target, key_type const& key); +}; + +// +// implementation +// +template +object_slice +object_operators::slice(object_cref start, object_cref finish) +{ + object_cref2 x = *static_cast(this); + return object_slice(x, std::make_pair(borrowed(start.ptr()), borrowed(finish.ptr()))); +} + +template +const_object_slice +object_operators::slice(object_cref start, object_cref finish) const +{ + object_cref2 x = *static_cast(this); + return const_object_slice(x, std::make_pair(borrowed(start.ptr()), borrowed(finish.ptr()))); +} + +template +object_slice +object_operators::slice(slice_nil, object_cref finish) +{ + object_cref2 x = *static_cast(this); + return object_slice(x, std::make_pair(allow_null((PyObject*)0), borrowed(finish.ptr()))); +} + +template +const_object_slice +object_operators::slice(slice_nil, object_cref finish) const +{ + object_cref2 x = *static_cast(this); + return const_object_slice(x, std::make_pair(allow_null((PyObject*)0), borrowed(finish.ptr()))); +} + +template +object_slice +object_operators::slice(object_cref start, slice_nil) +{ + object_cref2 x = *static_cast(this); + return object_slice(x, std::make_pair(borrowed(start.ptr()), allow_null((PyObject*)0))); +} + +template +const_object_slice +object_operators::slice(object_cref start, slice_nil) const +{ + object_cref2 x = *static_cast(this); + return const_object_slice(x, std::make_pair(borrowed(start.ptr()), allow_null((PyObject*)0))); +} +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +template +template +inline const_object_slice +object_operators::slice(T const& start, V const& end) const +{ + return this->slice( + typename slice_bound::type(start) + , typename slice_bound::type(end)); +} + +template +template +inline object_slice +object_operators::slice(T const& start, V const& end) +{ + return this->slice( + typename slice_bound::type(start) + , typename slice_bound::type(end)); +} +# endif + + +inline object const_slice_policies::get(object const& target, key_type const& key) +{ + return getslice(target, key.first, key.second); +} + +inline object const& slice_policies::set( + object const& target + , key_type const& key + , object const& value) +{ + setslice(target, key.first, key.second, value); + return value; +} + +inline void slice_policies::del( + object const& target + , key_type const& key) +{ + delslice(target, key.first, key.second); +} + +}}} // namespace boost::python::api + +#endif // OBJECT_SLICES_DWA2002615_HPP diff --git a/include/boost/python/objects.hpp b/include/boost/python/objects.hpp new file mode 100644 index 00000000..f2adb65b --- /dev/null +++ b/include/boost/python/objects.hpp @@ -0,0 +1,396 @@ +// (C) Copyright David Abrahams 2000. 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. +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +#ifndef OBJECTS_DWA051100_H_ +# define OBJECTS_DWA051100_H_ + +# ifdef BOOST_PYTHON_V2 +# error obsolete +# else +# include +# include +# include +# include "boost/operators.hpp" +# include + +namespace boost { namespace python { + +class BOOST_PYTHON_DECL object +{ + public: + explicit object(ref p); + + // Return a reference to the held object + ref reference() const; + + // Return a raw pointer to the held object + PyObject* get() const; + + private: + ref m_p; +}; + +class tuple; + +class BOOST_PYTHON_DECL tuple_base : public object +{ + public: + explicit tuple_base(std::size_t n = 0); + explicit tuple_base(ref p); + + static PyTypeObject* type_obj(); + static bool accepts(ref p); + std::size_t size() const; + ref operator[](std::size_t pos) const; + + void set_item(std::size_t pos, const ref& rhs); + + tuple slice(int low, int high) const; + + friend BOOST_PYTHON_DECL tuple operator+(const tuple&, const tuple&); + friend BOOST_PYTHON_DECL tuple& operator+=(tuple&, const tuple&); +}; + +class tuple : public tuple_base +{ + public: + explicit tuple(std::size_t n = 0) : tuple_base(n) {} + explicit tuple(ref p) : tuple_base(p) {} + + template + tuple(const std::pair& x) + : tuple_base(ref(PyTuple_New(2))) + { + set_item(0, x.first); + set_item(1, x.second); + } + + template + tuple(const First& first, const Second& second) + : tuple_base(ref(PyTuple_New(2))) + { + set_item(0, first); + set_item(1, second); + } + + template + tuple(const First& first, const Second& second, const Third& third) + : tuple_base(ref(PyTuple_New(3))) + { + set_item(0, first); + set_item(1, second); + set_item(2, third); + } + + template + tuple(const First& first, const Second& second, const Third& third, const Fourth& fourth) + : tuple_base(ref(PyTuple_New(4))) + { + set_item(0, first); + set_item(1, second); + set_item(2, third); + set_item(3, fourth); + } + + template + void set_item(std::size_t pos, const T& rhs) + { + this->set_item(pos, make_ref(rhs)); + } + + void set_item(std::size_t pos, const ref& rhs) + { + tuple_base::set_item(pos, rhs); + } +}; + +class list; + +struct BOOST_PYTHON_DECL list_proxy; +struct BOOST_PYTHON_DECL list_slice_proxy; + +class BOOST_PYTHON_DECL list_base : public object +{ + protected: + typedef list_proxy proxy; + typedef list_slice_proxy slice_proxy; + public: + explicit list_base(ref p); + explicit list_base(std::size_t sz = 0); + static PyTypeObject* type_obj(); + static bool accepts(ref p); + std::size_t size() const; + ref operator[](std::size_t pos) const; + proxy operator[](std::size_t pos); + ref get_item(std::size_t pos) const; + + void set_item(std::size_t pos, const ref& ); + +// void set_item(std::size_t pos, const object& ); + + void insert(std::size_t index, const ref& item); + + void push_back(const ref& item); + + void append(const ref& item); + + list slice(int low, int high) const; + slice_proxy slice(int low, int high); + void sort(); + void reverse(); + tuple as_tuple() const; +}; + +class list : public list_base +{ + public: + explicit list(ref p) : list_base(p) {} + explicit list(std::size_t sz = 0) : list_base(sz) {} + template + void set_item(std::size_t pos, const T& x) + { this->set_item(pos, make_ref(x)); } + template + void insert(std::size_t index, const T& x) + { this->insert(index, make_ref(x)); } + template + void push_back(const T& item) + { this->push_back(make_ref(item)); } + template + void append(const T& item) + { this->append(make_ref(item)); } + + void set_item(std::size_t pos, const ref& x) { list_base::set_item(pos, x); } + void insert(std::size_t index, const ref& item) { list_base::insert(index, item); } + void push_back(const ref& item) { list_base::push_back(item); } + void append(const ref& item) { list_base::append(item); } +}; + +class BOOST_PYTHON_DECL string + : public object, public boost::multipliable2 +{ + public: + // Construct from an owned PyObject*. + // Precondition: p must point to a python string. + explicit string(ref p); + explicit string(const char* s); + string(const char* s, std::size_t length); + string(const string& rhs); + + enum interned_t { interned }; + string(const char* s, interned_t); + + // Get the type object for Strings + static PyTypeObject* type_obj(); + + // Return true if the given object is a python string + static bool accepts(ref o); + + // Return the length of the string. + std::size_t size() const; + + // Returns a null-terminated representation of the contents of string. + // The pointer refers to the internal buffer of string, not a copy. + // The data must not be modified in any way. It must not be de-allocated. + const char* c_str() const; + + string& operator*=(unsigned int repeat_count); + string& operator+=(const string& rhs); + friend string operator+(string x, string y); + string& operator+=(const char* rhs); + friend string operator+(string x, const char* y); + friend string operator+(const char* x, string y); + + void intern(); + + friend string operator%(const string& format, const tuple& args); +}; + +class dictionary; + +struct BOOST_PYTHON_DECL dictionary_proxy; + +class BOOST_PYTHON_DECL dictionary_base : public object +{ + protected: + typedef dictionary_proxy proxy; + + public: + explicit dictionary_base(ref p); + dictionary_base(); + void clear(); + + static PyTypeObject* type_obj(); + static bool accepts(ref p); + + public: + proxy operator[](ref key); + ref operator[](ref key) const; + ref get_item(const ref& key) const; + ref get_item(const ref& key, const ref& default_) const; + + void set_item(const ref& key, const ref& value); + + void erase(ref key); + +// proxy operator[](const object& key); +// ref operator[](const object& key) const; + +// ref get_item(const object& key, ref default_ = ref()) const; +// void set_item(const object& key, const ref& value); + +// void erase(const object& key); + + list items() const; + list keys() const; + list values() const; + + std::size_t size() const; + // TODO: iterator support +}; + +struct BOOST_PYTHON_DECL dictionary_proxy +{ + template + const ref& operator=(const T& rhs) + { return (*this) = make_ref(rhs); } + const ref& operator=(const ref& rhs); + + operator ref() const; + private: + friend class dictionary_base; + dictionary_proxy(const ref& dict, const ref& key); + + // This is needed to work around the very strange MSVC error report that the + // return type of the built-in operator= differs from that of the ones + // defined above. Couldn't hurt to make these un-assignable anyway, though. + const ref& operator=(const dictionary_proxy&); // Not actually implemented + private: + ref m_dict; + ref m_key; +}; + +class dictionary : public dictionary_base +{ + typedef dictionary_proxy proxy; + public: + explicit dictionary(ref p) : dictionary_base(p) {} + dictionary() : dictionary_base() {} + + template + proxy operator[](const Key& key) + { return this->operator[](make_ref(key)); } + proxy operator[](ref key) + { return dictionary_base::operator[](key); } + + template + ref operator[](const Key& key) const + { return this->operator[](make_ref(key)); } + ref operator[](ref key) const + { return dictionary_base::operator[](key); } + + template + ref get_item(const Key& key) const + { return this->get_item(make_ref(key)); } + ref get_item(const ref& key) const + { return dictionary_base::get_item(key); } + + template + ref get_item(const Key& key, const Default& default_) const + { return this->get_item(make_ref(key), make_ref(default_)); } + ref get_item(const ref& key, const ref& default_) const + { return dictionary_base::get_item(key, default_); } + + template + void set_item(const Key& key, const Value& value) + { this->set_item(make_ref(key), make_ref(value)); } + void set_item(const ref& key, const ref& value) + { dictionary_base::set_item(key, value); } + + template + void erase(const Key& key) + { this->erase(make_ref(key)); } + void erase(ref key) + { dictionary_base::erase(key); } +}; + +struct BOOST_PYTHON_DECL list_proxy +{ + template + const ref& operator=(const T& rhs) + { return (*this) = make_ref(rhs); } + const ref& operator=(const ref& rhs); + + operator ref() const; + + private: + friend class list_base; + list_proxy(const ref& list, std::size_t index); + + // This is needed to work around the very strange MSVC error report that the + // return type of the built-in operator= differs from that of the ones + // defined above. Couldn't hurt to make these un-assignable anyway, though. + const ref& operator=(const list_proxy&); // Not actually implemented + private: + list m_list; + std::size_t m_index; +}; + +struct BOOST_PYTHON_DECL list_slice_proxy +{ + const list& operator=(const list& rhs); + operator ref() const; + operator list() const; + std::size_t size() const; + ref operator[](std::size_t pos) const; + private: + friend class list_base; + list_slice_proxy(const ref& list, int low, int high); + private: + ref m_list; + int m_low, m_high; +}; + +}} // namespace boost::python + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::tuple&); +BOOST_PYTHON_DECL boost::python::tuple from_python(PyObject* p, boost::python::type); + +inline boost::python::tuple from_python(PyObject* p, boost::python::type) +{ + return from_python(p, boost::python::type()); +} + +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::list&); +BOOST_PYTHON_DECL boost::python::list from_python(PyObject* p, boost::python::type); + +inline boost::python::list from_python(PyObject* p, boost::python::type) +{ + return from_python(p, boost::python::type()); +} + +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::string&); +BOOST_PYTHON_DECL boost::python::string from_python(PyObject* p, boost::python::type); + +inline boost::python::string from_python(PyObject* p, boost::python::type) +{ + return from_python(p, boost::python::type()); +} + +BOOST_PYTHON_DECL PyObject* to_python(const boost::python::dictionary&); +BOOST_PYTHON_DECL boost::python::dictionary from_python(PyObject* p, boost::python::type); + +inline boost::python::dictionary from_python(PyObject* p, boost::python::type) +{ + return from_python(p, boost::python::type()); +} + +BOOST_PYTHON_END_CONVERSION_NAMESPACE +# endif // !BOOST_PYTHON_V2 +#endif // OBJECTS_DWA051100_H_ diff --git a/include/boost/python/operators2.hpp b/include/boost/python/operators2.hpp new file mode 100755 index 00000000..8c56abf7 --- /dev/null +++ b/include/boost/python/operators2.hpp @@ -0,0 +1,340 @@ +// Copyright David Abrahams 2002. 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 OPERATORS2_DWA2002530_HPP +# define OPERATORS2_DWA2002530_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + // This is essentially the old v1 to_python(). It will be eliminated + // once the public interface for to_python is settled on. + template + PyObject* convert_result(T const& x) + { + return converter::arg_to_python(x).release(); + } + + // Operator implementation template declarations. The nested apply + // declaration here keeps MSVC6 happy. + template struct operator_l + { + template struct apply; + }; + + template struct operator_r + { + template struct apply; + }; + + template struct operator_1 + { + template struct apply; + }; + + // MSVC6 doesn't want us to do this sort of inheritance on a nested + // class template, so we use this layer of indirection to avoid + // ::template<...> on the nested apply functions below + template + struct operator_l_inner + : operator_l::template apply + {}; + + template + struct operator_r_inner + : operator_r::template apply + {}; + + template + struct operator_1_inner + : operator_1::template apply + {}; + + // Define three different binary_op templates which take care of + // these cases: + // self op self + // self op R + // L op self + // + // The inner apply metafunction is used to adjust the operator to + // the class type being defined. Inheritance of the outer class is + // simply used to provide convenient access to the operation's + // name(). + + // self op self + template + struct binary_op : operator_l + { + template + struct apply : operator_l_inner + { + }; + }; + + // self op R + template + struct binary_op_l : operator_l + { + template + struct apply : operator_l_inner + { + }; + }; + + // L op self + template + struct binary_op_r : operator_r + { + template + struct apply : operator_r_inner + { + }; + }; + + template + struct unary_op : operator_1 + { + template + struct apply : operator_1_inner + { + }; + }; + + // This type is what actually gets returned from operators used on + // self_t + template + struct operator_ + : mpl::select_type< + (is_same::value) + , typename mpl::select_type< + (is_same::value) + , binary_op + , binary_op_l::type> + >::type + , typename mpl::select_type< + (is_same::value) + , unary_op + , binary_op_r::type> + >::type + >::type + { + }; +} + +# define BOOST_PYTHON_BINARY_OPERATION(id, rid, expr) \ +namespace detail \ +{ \ + template <> \ + struct operator_l \ + { \ + template \ + struct apply \ + { \ + static inline PyObject* execute(L const& l, R const& r) \ + { \ + return detail::convert_result(expr); \ + } \ + }; \ + static char const* name() { return "__" #id "__"; } \ + }; \ + \ + template <> \ + struct operator_r \ + { \ + template \ + struct apply \ + { \ + static inline PyObject* execute(R const& r, L const& l) \ + { \ + return detail::convert_result(expr); \ + } \ + }; \ + static char const* name() { return "__" #rid "__"; } \ + }; \ +} + +# define BOOST_PYTHON_BINARY_OPERATOR(id, rid, op) \ +BOOST_PYTHON_BINARY_OPERATION(id, rid, l op r) \ +namespace self_ns \ +{ \ + template \ + inline detail::operator_ \ + operator##op(L const&, R const&) \ + { \ + return detail::operator_(); \ + } \ +} + +BOOST_PYTHON_BINARY_OPERATOR(add, radd, +) +BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -) +BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *) +BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /) +BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %) +BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<) +BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>) +BOOST_PYTHON_BINARY_OPERATOR(and, rand, &) +BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^) +BOOST_PYTHON_BINARY_OPERATOR(or, ror, |) +BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >) +BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=) +BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <) +BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=) +BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==) +BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=) +# undef BOOST_PYTHON_BINARY_OPERATOR + +// pow isn't an operator in C++; handle it specially. +BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r)) +# undef BOOST_PYTHON_BINARY_OPERATION + +namespace self_ns +{ +# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + template + inline detail::operator_ + pow(L const&, R const&) + { + return detail::operator_(); + } +# else + // When there's no argument-dependent lookup, we need these + // overloads to handle the case when everything is imported into the + // global namespace. Note that the plain overload below does /not/ + // take const& arguments. This is needed by MSVC6 at least, or it + // complains of ambiguities, since there's no partial ordering. + inline detail::operator_ + pow(self_t, self_t) + { + return detail::operator_(); + } + template + inline detail::operator_ + pow(self_t const&, R const&) + { + return detail::operator_(); + } + template + inline detail::operator_ + pow(L const&, self_t const&) + { + return detail::operator_(); + } +# endif +} + + +# define BOOST_PYTHON_INPLACE_OPERATOR(id, op) \ +namespace detail \ +{ \ + template <> \ + struct operator_l \ + { \ + template \ + struct apply \ + { \ + static inline PyObject* \ + execute(back_reference l, R const& r) \ + { \ + l.get() op r; \ + return python::incref(l.source().ptr()); \ + } \ + }; \ + static char const* name() { return "__" #id "__"; } \ + }; \ +} \ +namespace self_ns \ +{ \ + template \ + inline detail::operator_ \ + operator##op(self_t const&, R const&) \ + { \ + return detail::operator_(); \ + } \ +} + +BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=) +BOOST_PYTHON_INPLACE_OPERATOR(isub,-=) +BOOST_PYTHON_INPLACE_OPERATOR(imul,*=) +BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=) +BOOST_PYTHON_INPLACE_OPERATOR(imod,%=) +BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=) +BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=) +BOOST_PYTHON_INPLACE_OPERATOR(iand,&=) +BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=) +BOOST_PYTHON_INPLACE_OPERATOR(ior,|=) + +# define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name) \ +namespace detail \ +{ \ + template <> \ + struct operator_1 \ + { \ + template \ + struct apply \ + { \ + static PyObject* execute(T const& x) \ + { \ + return detail::convert_result(op(x)); \ + } \ + }; \ + static char const* name() { return "__" #id "__"; } \ + }; \ +} \ +namespace self_ns \ +{ \ + inline detail::operator_ \ + func_name(self_t const&) \ + { \ + return detail::operator_(); \ + } \ +} +# undef BOOST_PYTHON_INPLACE_OPERATOR + +BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-) +BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+) +BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs) +BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~) +BOOST_PYTHON_UNARY_OPERATOR(int, long, int_) +BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_) +BOOST_PYTHON_UNARY_OPERATOR(float, double, float_) +BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex, complex_) +BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast, str) +# undef BOOST_PYTHON_UNARY_OPERATOR + +}} // namespace boost::python + +# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +using boost::python::self_ns::abs; +using boost::python::self_ns::int_; +using boost::python::self_ns::long_; +using boost::python::self_ns::float_; +using boost::python::self_ns::complex_; +using boost::python::self_ns::str; +using boost::python::self_ns::pow; +# endif + +#endif // OPERATORS2_DWA2002530_HPP + + + + + + + + diff --git a/include/boost/python/py_interface.hpp b/include/boost/python/py_interface.hpp new file mode 100644 index 00000000..c1416d5c --- /dev/null +++ b/include/boost/python/py_interface.hpp @@ -0,0 +1,700 @@ +// Automatically generated from py_api_gen.py +#ifndef PY_INTERFACE_HPP +#define PY_INTERFACE_HPP + +#include +#include + +namespace boost { namespace python { namespace api { + +enum call_dict_usage { use_new_dict, use_local_dict, use_global_dict }; + +namespace api_detail { + +BOOST_PYTHON_DECL object get_func(const char* name); +BOOST_PYTHON_DECL object call_statement(const char *stmt, int n, ...); +BOOST_PYTHON_DECL object call_statement_du(const char *stmt, call_dict_usage cdu, int n, ...); + +template +struct get_arg +{ + get_arg(A const &a) : h(a) {} + object h; + operator object const& () { return h; } + operator object const* () { return &h; } +}; + +template<> +struct get_arg +{ + get_arg(object const &a) : h(a) {} + object const &h; + operator object const& () { return h; } + operator object const* () { return &h; } +}; + +template<> +struct get_arg +{ + get_arg(PyObject* a) : h((python::detail::borrowed_reference)a) {} + object h; + operator object const& () { return h; } + operator object const* () { return &h; } +}; + +} + +BOOST_PYTHON_DECL object locals(); + + +template +object abs(A0 const& a0) +{ + return api_detail::get_func("abs")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object abs(object const& a0); +BOOST_PYTHON_DECL object abs(short a0); +BOOST_PYTHON_DECL object abs(int a0); +BOOST_PYTHON_DECL object abs(long a0); +BOOST_PYTHON_DECL object abs(double const & a0); +BOOST_PYTHON_DECL object apply(object const& a0, object const& a1); +BOOST_PYTHON_DECL object apply(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL bool callable(object const& a0); +template +object chr(A0 const& a0) +{ + return api_detail::get_func("chr")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object chr(object const& a0); +BOOST_PYTHON_DECL object chr(short a0); +BOOST_PYTHON_DECL object chr(int a0); +BOOST_PYTHON_DECL object chr(long a0); +template +int cmp(A0 const& a0, A1 const& a1) +{ + int rslt; + int r = ::PyObject_Cmp(api_detail::get_arg(a0), api_detail::get_arg(a1), &rslt); + if(r == -1) + throw_error_already_set(); + return rslt; +} +BOOST_PYTHON_DECL int cmp(object const& a0, object const& a1); +BOOST_PYTHON_DECL object coerce(object const& a0, object const& a1); +BOOST_PYTHON_DECL object compile(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object compile(const char* a0, const char* a1, const char* a2); +BOOST_PYTHON_DECL object compile(object const& a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object compile(const char* a0, const char* a1, const char* a2, int a3); +BOOST_PYTHON_DECL object compile(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object compile(const char* a0, const char* a1, const char* a2, int a3, int a4); +template +object complex(A0 const& a0) +{ + return api_detail::get_func("complex")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object complex(object const& a0); +BOOST_PYTHON_DECL object complex(double const& a0); +template +object complex(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("complex")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +BOOST_PYTHON_DECL object complex(object const& a0, object const& a1); +BOOST_PYTHON_DECL object complex(double const& a0, double const& a1); +BOOST_PYTHON_DECL object dict(); +BOOST_PYTHON_DECL object dict(object const& a0); +BOOST_PYTHON_DECL object dir(); +BOOST_PYTHON_DECL object dir(object const& a0); +template +object divmod(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("divmod")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +BOOST_PYTHON_DECL object divmod(object const& a0, object const& a1); +BOOST_PYTHON_DECL object divmod(int a0, int a1); +BOOST_PYTHON_DECL object divmod(long a0, long a1); +BOOST_PYTHON_DECL object divmod(double const& a0, double const& a1); +BOOST_PYTHON_DECL object eval(const char* a0); +BOOST_PYTHON_DECL object eval(const char* a0, object const& a2); +BOOST_PYTHON_DECL object eval(const char* a0, object const& a2, object const& a3); +BOOST_PYTHON_DECL object exec(const char* a0); +BOOST_PYTHON_DECL object exec(const char* a0, object const& a2); +BOOST_PYTHON_DECL object exec(const char* a0, object const& a2, object const& a3); +BOOST_PYTHON_DECL object execfile(object const& a0); +BOOST_PYTHON_DECL object execfile(object const& a0, object const& a1); +BOOST_PYTHON_DECL object execfile(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object file(object const& a0); +BOOST_PYTHON_DECL object file(const char* a0); +BOOST_PYTHON_DECL object file(object const& a0, object const& a1); +BOOST_PYTHON_DECL object file(const char* a0, const char* a1); +BOOST_PYTHON_DECL object file(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object file(const char* a0, const char* a1, int a2); +BOOST_PYTHON_DECL object filter(object const& a0, object const& a1); +BOOST_PYTHON_DECL object float_(object const& a0); +BOOST_PYTHON_DECL object float_(const char* a0); +BOOST_PYTHON_DECL object float_(double const& a0); +BOOST_PYTHON_DECL object getattr(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object getattr(object const& a0, const char * a1, object const& a2); +BOOST_PYTHON_DECL object globals(); +BOOST_PYTHON_DECL bool hasattr(object const& a0, object const& a1); +BOOST_PYTHON_DECL bool hasattr(object const& a0, const char* a1); +BOOST_PYTHON_DECL long hash(object const& a0); +template +object hex(A0 const& a0) +{ + return api_detail::get_func("hex")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object hex(object const& a0); +BOOST_PYTHON_DECL object hex(char a0); +BOOST_PYTHON_DECL object hex(short a0); +BOOST_PYTHON_DECL object hex(int a0); +BOOST_PYTHON_DECL object hex(long a0); +BOOST_PYTHON_DECL long id(object const& a0); +BOOST_PYTHON_DECL object input(); +BOOST_PYTHON_DECL object input(object const& a0); +BOOST_PYTHON_DECL object input(const char* a0); +BOOST_PYTHON_DECL object int_(object const& a0); +BOOST_PYTHON_DECL object int_(long a0); +BOOST_PYTHON_DECL object int_(const char* a0); +BOOST_PYTHON_DECL object intern(object const& a0); +BOOST_PYTHON_DECL object intern(const char* a0); +BOOST_PYTHON_DECL bool isinstance(object const& a0, object const& a1); +BOOST_PYTHON_DECL bool issubclass(object const& a0, object const& a1); +BOOST_PYTHON_DECL object iter(object const& a0); +BOOST_PYTHON_DECL object iter(object const& a0, object const& a1); +BOOST_PYTHON_DECL long len(object const& a0); +BOOST_PYTHON_DECL object list(); +BOOST_PYTHON_DECL object list(object const& a0); +BOOST_PYTHON_DECL object long_(object const& a0); +BOOST_PYTHON_DECL object long_(long a0); +BOOST_PYTHON_DECL object long_(const char* a0); +BOOST_PYTHON_DECL object map(object const& a0); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object map(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +template +object max(A0 const& a0) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0)); +} +template +object max(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6), api_detail::get_arg(a7)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6), api_detail::get_arg(a7), api_detail::get_arg(a8)); +} +template +object max(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9) +{ + return api_detail::get_func("max")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6), api_detail::get_arg(a7), api_detail::get_arg(a8), api_detail::get_arg(a9)); +} +BOOST_PYTHON_DECL object max(object const& a0); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object max(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +template +object min(A0 const& a0) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0)); +} +template +object min(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6), api_detail::get_arg(a7)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6), api_detail::get_arg(a7), api_detail::get_arg(a8)); +} +template +object min(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9) +{ + return api_detail::get_func("min")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2), api_detail::get_arg(a3), api_detail::get_arg(a4), api_detail::get_arg(a5), api_detail::get_arg(a6), api_detail::get_arg(a7), api_detail::get_arg(a8), api_detail::get_arg(a9)); +} +BOOST_PYTHON_DECL object min(object const& a0); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object min(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +template +object oct(A0 const& a0) +{ + return api_detail::get_func("oct")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object oct(object const& a0); +BOOST_PYTHON_DECL object oct(char a0); +BOOST_PYTHON_DECL object oct(short a0); +BOOST_PYTHON_DECL object oct(int a0); +BOOST_PYTHON_DECL object oct(long a0); +BOOST_PYTHON_DECL object open(object const& a0); +BOOST_PYTHON_DECL object open(const char* a0); +BOOST_PYTHON_DECL object open(object const& a0, object const& a1); +BOOST_PYTHON_DECL object open(const char* a0, const char* a1); +BOOST_PYTHON_DECL object open(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object open(const char* a0, const char* a1, int a2); +BOOST_PYTHON_DECL long ord(object const& a0); +BOOST_PYTHON_DECL long ord(const char* a0); +template +object pow(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("pow")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +BOOST_PYTHON_DECL object pow(object const& a0, object const& a1); +BOOST_PYTHON_DECL object pow(double const& a0, double const& a1); +BOOST_PYTHON_DECL object pow(double const& a0, double const& a1, double const& a2); +template +object print(A0 const& a0) +{ + return api_detail::call_statement_du("print _1", use_new_dict, 1, (object const*)api_detail::get_arg(a0)); +} +template +object print(A0 const& a0, A1 const& a1) +{ + return api_detail::call_statement_du("print _1, _2", use_new_dict, 2, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2) +{ + return api_detail::call_statement_du("print _1, _2, _3", use_new_dict, 3, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) +{ + return api_detail::call_statement_du("print _1, _2, _3, _4", use_new_dict, 4, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4) +{ + return api_detail::call_statement_du("print _1, _2, _3, _4, _5", use_new_dict, 5, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5) +{ + return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6", use_new_dict, 6, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6) +{ + return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7", use_new_dict, 7, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7) +{ + return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7, _8", use_new_dict, 8, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8) +{ + return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7, _8, _9", use_new_dict, 9, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8)); +} +template +object print(A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9) +{ + return api_detail::call_statement_du("print _1, _2, _3, _4, _5, _6, _7, _8, _9, _10", use_new_dict, 10, (object const*)api_detail::get_arg(a0), (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9)); +} +BOOST_PYTHON_DECL object print(object const& a0); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object print(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +template +object print_file(object const& a0, A1 const& a1) +{ + return api_detail::call_statement_du("print >>_1, _2", use_new_dict, 2, a0, (object const*)api_detail::get_arg(a1)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2) +{ + return api_detail::call_statement_du("print >>_1, _2, _3", use_new_dict, 3, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4", use_new_dict, 4, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5", use_new_dict, 5, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6", use_new_dict, 6, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7", use_new_dict, 7, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8", use_new_dict, 8, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8, _9", use_new_dict, 9, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8, _9, _10", use_new_dict, 10, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9)); +} +template +object print_file(object const& a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9, A10 const& a10) +{ + return api_detail::call_statement_du("print >>_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11", use_new_dict, 11, a0, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9), (object const*)api_detail::get_arg(a10)); +} +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +BOOST_PYTHON_DECL object print_file(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10); +template +object range(A0 const& a0) +{ + return api_detail::get_func("range")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object range(object const& a0); +BOOST_PYTHON_DECL object range(int a0); +template +object range(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("range")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +BOOST_PYTHON_DECL object range(object const& a0, object const& a1); +BOOST_PYTHON_DECL object range(int a0, int a1); +template +object range(A0 const& a0, A1 const& a1, A2 const& a2) +{ + return api_detail::get_func("range")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2)); +} +BOOST_PYTHON_DECL object range(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object range(int a0, int a1, int a2); +BOOST_PYTHON_DECL object raw_input(); +BOOST_PYTHON_DECL object raw_input(object const& a0); +BOOST_PYTHON_DECL object raw_input(const char* a0); +BOOST_PYTHON_DECL object reduce(object const& a0, object const& a1); +BOOST_PYTHON_DECL object reduce(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object reload(object const& a0); +BOOST_PYTHON_DECL object repr(object const& a0); +template +object round(A0 const& a0) +{ + return api_detail::get_func("round")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object round(object const& a0); +BOOST_PYTHON_DECL object round(double const& a0); +template +object round(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("round")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +BOOST_PYTHON_DECL object round(object const& a0, object const& a1); +BOOST_PYTHON_DECL object round(double const& a0, double const& a1); +template +object slice(A0 const& a0) +{ + return api_detail::get_func("slice")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object slice(object const& a0); +BOOST_PYTHON_DECL object slice(int a0); +template +object slice(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("slice")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +BOOST_PYTHON_DECL object slice(object const& a0, object const& a1); +BOOST_PYTHON_DECL object slice(int a0, int a1); +template +object slice(A0 const& a0, A1 const& a1, A2 const& a2) +{ + return api_detail::get_func("slice")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2)); +} +BOOST_PYTHON_DECL object slice(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object slice(int a0, int a1, int a2); +BOOST_PYTHON_DECL object str(object const& a0); +BOOST_PYTHON_DECL object tuple(); +BOOST_PYTHON_DECL object tuple(object const& a0); +BOOST_PYTHON_DECL object type_(object const& a0); +template +object unichr(A0 const& a0) +{ + return api_detail::get_func("unichr")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object unichr(object const& a0); +BOOST_PYTHON_DECL object unichr(short a0); +BOOST_PYTHON_DECL object unichr(int a0); +BOOST_PYTHON_DECL object unichr(long a0); +BOOST_PYTHON_DECL object unicode(object const& a0); +BOOST_PYTHON_DECL object unicode(object const& a0, object const& a1); +BOOST_PYTHON_DECL object unicode(object const& a0, const char* a1); +BOOST_PYTHON_DECL object unicode(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object unicode(object const& a0, const char* a1, const char* a2); +BOOST_PYTHON_DECL object vars(); +BOOST_PYTHON_DECL object vars(object const& a0); +template +object xrange(A0 const& a0) +{ + return api_detail::get_func("xrange")(api_detail::get_arg(a0)); +} +BOOST_PYTHON_DECL object xrange(object const& a0); +BOOST_PYTHON_DECL object xrange(int a0); +template +object xrange(A0 const& a0, A1 const& a1) +{ + return api_detail::get_func("xrange")(api_detail::get_arg(a0), api_detail::get_arg(a1)); +} +BOOST_PYTHON_DECL object xrange(object const& a0, object const& a1); +BOOST_PYTHON_DECL object xrange(int a0, int a1); +template +object xrange(A0 const& a0, A1 const& a1, A2 const& a2) +{ + return api_detail::get_func("xrange")(api_detail::get_arg(a0), api_detail::get_arg(a1), api_detail::get_arg(a2)); +} +BOOST_PYTHON_DECL object xrange(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object xrange(int a0, int a1, int a2); +BOOST_PYTHON_DECL object zip(object const& a0); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object zip(object const& a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +BOOST_PYTHON_DECL object compile_string(const char* a0, const char* a1, int a2); +BOOST_PYTHON_DECL int import_append_inittab(const char* a0, void(*a1)(void)); +BOOST_PYTHON_DECL object import_add_module(const char* a0); +BOOST_PYTHON_DECL object import_get_module_dict(); +BOOST_PYTHON_DECL object import_import(object const& a0); +BOOST_PYTHON_DECL object import_import(const char* a0); +BOOST_PYTHON_DECL object import_import_module(const char* a0); +BOOST_PYTHON_DECL object import_import_module_ex(const char* a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object module_get_dict(object const& a0); +BOOST_PYTHON_DECL int object_print(object const& a0, FILE* a1, int a2); +BOOST_PYTHON_DECL object run_file(FILE* a0, const char* a1, int a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL int run_simple_file(FILE* a0, const char* a1); +BOOST_PYTHON_DECL int run_simple_string(const char* a0); +BOOST_PYTHON_DECL object run_string(const char* a0, int a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object call_statement(const char* a0); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1); +template +object call_statement(const char* a0, A1 const& a1) +{ + return api_detail::call_statement(a0, 1, (object const*)api_detail::get_arg(a1)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2) +{ + return api_detail::call_statement(a0, 2, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3) +{ + return api_detail::call_statement(a0, 3, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4) +{ + return api_detail::call_statement(a0, 4, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5) +{ + return api_detail::call_statement(a0, 5, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6) +{ + return api_detail::call_statement(a0, 6, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7) +{ + return api_detail::call_statement(a0, 7, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8) +{ + return api_detail::call_statement(a0, 8, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9) +{ + return api_detail::call_statement(a0, 9, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9)); +} +template +object call_statement(const char* a0, A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9, A10 const& a10) +{ + return api_detail::call_statement(a0, 10, (object const*)api_detail::get_arg(a1), (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9), (object const*)api_detail::get_arg(a10)); +} +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +BOOST_PYTHON_DECL object call_statement(const char* a0, object const& a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10); +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2) +{ + return api_detail::call_statement_du(a0, a1, 1, (object const*)api_detail::get_arg(a2)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3) +{ + return api_detail::call_statement_du(a0, a1, 2, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4) +{ + return api_detail::call_statement_du(a0, a1, 3, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5) +{ + return api_detail::call_statement_du(a0, a1, 4, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6) +{ + return api_detail::call_statement_du(a0, a1, 5, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7) +{ + return api_detail::call_statement_du(a0, a1, 6, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8) +{ + return api_detail::call_statement_du(a0, a1, 7, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9) +{ + return api_detail::call_statement_du(a0, a1, 8, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9, A10 const& a10) +{ + return api_detail::call_statement_du(a0, a1, 9, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9), (object const*)api_detail::get_arg(a10)); +} +template +object call_statement(const char* a0, call_dict_usage a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7, A8 const& a8, A9 const& a9, A10 const& a10, A11 const& a11) +{ + return api_detail::call_statement_du(a0, a1, 10, (object const*)api_detail::get_arg(a2), (object const*)api_detail::get_arg(a3), (object const*)api_detail::get_arg(a4), (object const*)api_detail::get_arg(a5), (object const*)api_detail::get_arg(a6), (object const*)api_detail::get_arg(a7), (object const*)api_detail::get_arg(a8), (object const*)api_detail::get_arg(a9), (object const*)api_detail::get_arg(a10), (object const*)api_detail::get_arg(a11)); +} +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10); +BOOST_PYTHON_DECL object call_statement(const char* a0, call_dict_usage a1, object const& a2, object const& a3, object const& a4, object const& a5, object const& a6, object const& a7, object const& a8, object const& a9, object const& a10, object const& a11); + +}}} + +#endif // PY_INTERFACE_HPP + diff --git a/include/boost/python/return_internal_reference.hpp b/include/boost/python/return_internal_reference.hpp new file mode 100644 index 00000000..3a968f45 --- /dev/null +++ b/include/boost/python/return_internal_reference.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. 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 RETURN_INTERNAL_REFERENCE_DWA2002131_HPP +# define RETURN_INTERNAL_REFERENCE_DWA2002131_HPP + +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct return_internal_reference_owner_arg_must_be_greater_than_zero +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template +struct return_internal_reference + : with_custodian_and_ward_postcall<0, owner_arg, BasePolicy_> +{ + private: + BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0); + public: + typedef typename mpl::select_type< + legal + , reference_existing_object + , detail::return_internal_reference_owner_arg_must_be_greater_than_zero + >::type result_converter; +}; + +}} // namespace boost::python + +#endif // RETURN_INTERNAL_REFERENCE_DWA2002131_HPP diff --git a/include/boost/python/return_value_policy.hpp b/include/boost/python/return_value_policy.hpp new file mode 100644 index 00000000..0f3c00fe --- /dev/null +++ b/include/boost/python/return_value_policy.hpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2002. 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 RETURN_VALUE_POLICY_DWA2002131_HPP +# define RETURN_VALUE_POLICY_DWA2002131_HPP +# include + +namespace boost { namespace python { + +template +struct return_value_policy : BasePolicy_ +{ + typedef ResultConverterGenerator result_converter; +}; + +}} // namespace boost::python + +#endif // RETURN_VALUE_POLICY_DWA2002131_HPP diff --git a/include/boost/python/scope.hpp b/include/boost/python/scope.hpp new file mode 100644 index 00000000..7262f8da --- /dev/null +++ b/include/boost/python/scope.hpp @@ -0,0 +1,64 @@ +// Copyright David Abrahams 2002. 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 SCOPE_DWA2002724_HPP +# define SCOPE_DWA2002724_HPP + +# include +# include +# include + +namespace boost { namespace python { + +class BOOST_PYTHON_DECL scope + : public object, private noncopyable +{ + public: + inline scope(object const&); + inline scope(); + inline ~scope(); + + private: // data members + PyObject* m_previous_scope; + + private: // static members + + // Use a PyObject* to avoid problems with static destruction after Py_Finalize + static PyObject* current_scope; +}; + +inline scope::scope(object const& new_scope) + : object(new_scope) + , m_previous_scope(current_scope) +{ + current_scope = python::incref(new_scope.ptr()); +} + +inline scope::scope() + : object(detail::borrowed_reference( + current_scope ? current_scope : Py_None + )) + , m_previous_scope(python::xincref(current_scope)) +{ +} + +inline scope::~scope() +{ + python::xdecref(current_scope); + current_scope = m_previous_scope; +} + +namespace converter +{ + template <> + struct object_manager_traits + : object_manager_traits + { + }; +} + +}} // namespace boost::python + +#endif // SCOPE_DWA2002724_HPP diff --git a/include/boost/python/self.hpp b/include/boost/python/self.hpp new file mode 100755 index 00000000..c7d3f670 --- /dev/null +++ b/include/boost/python/self.hpp @@ -0,0 +1,36 @@ +// Copyright David Abrahams 2002. 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 SELF_DWA2002531_HPP +# define SELF_DWA2002531_HPP + +# include + +namespace boost { namespace python { + +//# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 +# define BOOST_PYTHON_SELF_IS_CLASS +//# endif + +// Sink self_t into its own namespace so that we have a safe place to +// put the completely general operator templates which operate on +// it. It is possible to avoid this, but it turns out to be much more +// complicated and finally GCC 2.95.2 chokes on it. +namespace self_ns +{ +# ifndef BOOST_PYTHON_SELF_IS_CLASS + enum self_t { self }; +# else + struct self_t {}; + extern BOOST_PYTHON_DECL self_t self; +# endif +} + +using self_ns::self_t; +using self_ns::self; + +}} // namespace boost::python + +#endif // SELF_DWA2002531_HPP diff --git a/include/boost/python/signature.hpp b/include/boost/python/signature.hpp new file mode 100644 index 00000000..3bef081e --- /dev/null +++ b/include/boost/python/signature.hpp @@ -0,0 +1,121 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002. 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. +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_PP_IS_ITERATING) + +# ifndef SIGNATURE_JDG20020813_HPP +# define SIGNATURE_JDG20020813_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace python { namespace detail { + +/////////////////////////////////////////////////////////////////////////////// +// +// The following macros generate expansions for: +// +// template +// inline boost::mpl::type_list +// get_signature(RT(*)(T0...TN)) +// { +// return boost::mpl::type_list(); +// } +// +// template +// inline boost::mpl::type_list +// get_signature(RT(ClassT::*)(T0...TN))) +// { +// return boost::mpl::type_list(); +// } +// +// template +// inline boost::mpl::type_list +// get_signature(RT(ClassT::*)(T0...TN) const)) +// { +// return boost::mpl::type_list(); +// } +// +// These functions extract the return type, class (for member functions) +// and arguments of the input signature and stuffs them in an mpl::type_list. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY-1, )) + +# include BOOST_PP_ITERATE() + +} + +}} // namespace boost::python + +/////////////////////////////////////////////////////////////////////////////// +# endif // SIGNATURE_JDG20020813_HPP + +#else // defined(BOOST_PP_IS_ITERATING) + +# define N BOOST_PP_ITERATION() + +template < + class RT BOOST_PP_COMMA_IF(N) + BOOST_PYTHON_UNARY_ENUM(N, class T)> +inline boost::mpl::type_list< + RT BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM_PARAMS(N, T)> +get_signature(RT(*)(BOOST_PP_ENUM_PARAMS(N, T))) +{ + return boost::mpl::type_list< + RT BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM_PARAMS(N, T)>(); +} + +/////////////////////////////////////////////////////////////////////////////// +#if N <= (BOOST_PYTHON_MAX_ARITY - 2) + +template < + class RT, class ClassT BOOST_PP_COMMA_IF(N) + BOOST_PYTHON_UNARY_ENUM(N, class T)> +inline boost::mpl::type_list< + RT, ClassT BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM_PARAMS(N, T)> +get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS(N, T))) +{ + return boost::mpl::type_list< + RT, ClassT BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM_PARAMS(N, T)>(); +} + +/////////////////////////////////////// +template < + class RT, class ClassT BOOST_PP_COMMA_IF(N) + BOOST_PYTHON_UNARY_ENUM(N, class T)> +inline boost::mpl::type_list< + RT, ClassT const BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM_PARAMS(N, T)> +get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS(N, T)) const) +{ + return boost::mpl::type_list< + RT, ClassT const + BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM_PARAMS(N, T)>(); +} + +#endif // N < (BOOST_PYTHON_MAX_ARITY - 2) + +#endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/include/boost/python/slice_nil.hpp b/include/boost/python/slice_nil.hpp new file mode 100644 index 00000000..cb169116 --- /dev/null +++ b/include/boost/python/slice_nil.hpp @@ -0,0 +1,41 @@ +// Copyright David Abrahams 2002. 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 SLICE_NIL_DWA2002620_HPP +# define SLICE_NIL_DWA2002620_HPP + +namespace boost { namespace python { namespace api { + +class object; + +enum slice_nil +{ +# ifndef _ // Watch out for GNU gettext users, who #define _(x) + _ +# endif +}; + +template +struct slice_bound +{ + typedef object type; +}; + +template <> +struct slice_bound +{ + typedef slice_nil type; +}; + +} + +using api::slice_nil; +# ifndef _ // Watch out for GNU gettext users, who #define _(x) +using api::_; +# endif + +}} // namespace boost::python + +#endif // SLICE_NIL_DWA2002620_HPP diff --git a/include/boost/python/str.hpp b/include/boost/python/str.hpp new file mode 100644 index 00000000..fb8bfe58 --- /dev/null +++ b/include/boost/python/str.hpp @@ -0,0 +1,375 @@ +#ifndef STR_20020703_HPP +#define STR_20020703_HPP + +#include +#include +#include + +// disable defines in provided by some system libraries +#undef isspace +#undef islower +#undef isalpha +#undef isdigit +#undef isalnum +#undef isupper + +namespace boost { namespace python { + +class str : public object +{ + public: + BOOST_PYTHON_DECL str(); // new str + + BOOST_PYTHON_DECL str(const char* s); // new str + explicit BOOST_PYTHON_DECL str(object_cref other); + + template + explicit str(T const& other) + : object(str::call(object(other))) + { + } + + BOOST_PYTHON_DECL str capitalize() const ; + + BOOST_PYTHON_DECL str center(object_cref width) const ; + + template + str center(T const& width) const + { + return this->center(object(width)); + } + + BOOST_PYTHON_DECL long count(object_cref sub) const; + + template + long count(T const& sub) const + { + return this->count(object(sub)); + } + + BOOST_PYTHON_DECL long count(object_cref sub, object_cref start) const; + + template + long count(T1 const& sub,T2 const& start) const + { + return this->count(object(sub), object(start)); + } + + BOOST_PYTHON_DECL long count(object_cref sub, object_cref start, object_cref end) const; + + template + long count(T1 const& sub,T2 const& start, T3 const& end) const + { + return this->count(object(sub), object(start)); + } + + BOOST_PYTHON_DECL object decode() const; + BOOST_PYTHON_DECL object decode(object_cref encoding) const; + + template + object decode(T const& encoding) const + { + return this->decode(object(encoding)); + } + + BOOST_PYTHON_DECL object decode(object_cref encoding, object_cref errors) const; + + template + object decode(T1 const& encoding, T2 const& errors) const + { + return this->decode(object(encoding),object(errors)); + } + + BOOST_PYTHON_DECL object encode() const; + BOOST_PYTHON_DECL object encode(object_cref encoding) const; + + template + object encode(T const& encoding) const + { + return this->encode(object(encoding)); + } + + BOOST_PYTHON_DECL object encode(object_cref encoding, object_cref errors) const; + + template + object encode(T1 const& encoding, T2 const& errors) const + { + return this->encode(object(encoding),object(errors)); + } + + BOOST_PYTHON_DECL bool endswith(object_cref suffix) const; + + template + bool endswith(T const& suffix) const + { + return this->endswith(object(suffix)); + } + + BOOST_PYTHON_DECL bool endswith(object_cref suffix, object_cref start) const; + + template + bool endswith(T1 const& suffix, T2 const& start) const + { + return this->endswith(object(suffix), object(start)); + } + + BOOST_PYTHON_DECL bool endswith(object_cref suffix, object_cref start, object_cref end) const; + + template + bool endswith(T1 const& suffix, T2 const& start, T3 const& end) const + { + return this->endswith(object(suffix), object(start), object(end)); + } + + BOOST_PYTHON_DECL str expandtabs() const; + BOOST_PYTHON_DECL str expandtabs(object_cref tabsize) const; + + template + str expandtabs(T const& tabsize) const + { + return this->expandtabs(object(tabsize)); + } + + BOOST_PYTHON_DECL long find(object_cref sub) const; + + template + long find(T const& sub) const + { + return this->find(object(sub)); + } + + BOOST_PYTHON_DECL long find(object_cref sub, object_cref start) const; + + template + long find(T1 const& sub, T2 const& start) const + { + return this->find(object(sub), object(start)); + } + + BOOST_PYTHON_DECL long find(object_cref sub, object_cref start, object_cref end) const; + + template + long find(T1 const& sub, T2 const& start, T3 const& end) const + { + return this->find(object(sub), object(start), object(end)); + } + + BOOST_PYTHON_DECL long index(object_cref sub) const; + + template + long index(T const& sub) const + { + return this->index(object(sub)); + } + + BOOST_PYTHON_DECL long index(object_cref sub, object_cref start) const; + + template + long index(T1 const& sub, T2 const& start) const + { + return this->index(object(sub), object(start)); + } + + BOOST_PYTHON_DECL long index(object_cref sub, object_cref start, object_cref end) const; + + template + long index(T1 const& sub, T2 const& start, T3 const& end) const + { + return this->index(object(sub), object(start), object(end)); + } + + BOOST_PYTHON_DECL bool isalnum() const; + BOOST_PYTHON_DECL bool isalpha() const; + BOOST_PYTHON_DECL bool isdigit() const; + BOOST_PYTHON_DECL bool islower() const; + BOOST_PYTHON_DECL bool isspace() const; + BOOST_PYTHON_DECL bool istitle() const; + BOOST_PYTHON_DECL bool isupper() const; + + BOOST_PYTHON_DECL str join(object_cref sequence) const; + + template + str join(T const& sequence) const + { + return this->join(object(sequence)); + } + + BOOST_PYTHON_DECL str ljust(object_cref width) const; + + template + str ljust(T const& width) const + { + return this->ljust(object(width)); + } + + BOOST_PYTHON_DECL str lower() const; + BOOST_PYTHON_DECL str lstrip() const; + + BOOST_PYTHON_DECL str replace(object_cref old, object_cref new_) const ; + + template + str replace(T1 const& old, T2 const& new_) const + { + return this->replace(object(old),object(new_)); + } + + BOOST_PYTHON_DECL str replace(object_cref old, object_cref new_, object_cref maxsplit) const ; + + template + str replace(T1 const& old, T2 const& new_, T3 const& maxsplit) const + { + return this->replace(object(old),object(new_),object(maxsplit)); + } + + BOOST_PYTHON_DECL long rfind(object_cref sub) const; + + template + long rfind(T const& sub) const + { + return this->rfind(object(sub)); + } + + BOOST_PYTHON_DECL long rfind(object_cref sub, object_cref start) const; + + template + long rfind(T1 const& sub, T2 const& start) const + { + return this->rfind(object(sub), object(start)); + } + + BOOST_PYTHON_DECL long rfind(object_cref sub, object_cref start, object_cref end) const; + + template + long rfind(T1 const& sub, T2 const& start, T3 const& end) const + { + return this->rfind(object(sub), object(start), object(end)); + } + + BOOST_PYTHON_DECL long rindex(object_cref sub) const; + + template + long rindex(T const& sub) const + { + return this->rindex(object(sub)); + } + + BOOST_PYTHON_DECL long rindex(object_cref sub, object_cref start) const; + + template + long rindex(T1 const& sub, T2 const& start) const + { + return this->rindex(object(sub), object(start)); + } + + BOOST_PYTHON_DECL long rindex(object_cref sub, object_cref start, object_cref end) const; + + template + long rindex(T1 const& sub, T2 const& start, T3 const& end) const + { + return this->rindex(object(sub), object(start), object(end)); + } + + BOOST_PYTHON_DECL str rjust(object_cref width) const; + + template + str rjust(T const& width) const + { + return this->rjust(object(width)); + } + + BOOST_PYTHON_DECL str rstrip() const; + + BOOST_PYTHON_DECL list split() const; + BOOST_PYTHON_DECL list split(object_cref sep) const; + + template + list split(T const& sep) const + { + return this->split(object(sep)); + } + + BOOST_PYTHON_DECL list split(object_cref sep, object_cref maxsplit) const; + + template + list split(T1 const& sep, T2 const& maxsplit) const + { + return this->split(object(sep), object(maxsplit)); + } + + BOOST_PYTHON_DECL list splitlines() const; + BOOST_PYTHON_DECL list splitlines(object_cref keepends) const; + + template + list splitlines(T const& keepends) const + { + return this->splitlines(object(keepends)); + } + + BOOST_PYTHON_DECL bool startswith(object_cref prefix) const ; + + template + bool startswith(T const& prefix) const + { + return this->startswith(object(prefix)); + } + + BOOST_PYTHON_DECL bool startswith(object_cref prefix, object_cref start) const ; + + template + bool startswidth(T1 const& prefix, T2 const& start) const + { + return this->startswidth(object(prefix), object(start)); + } + + BOOST_PYTHON_DECL bool startswith(object_cref prefix, object_cref start, object_cref end) const ; + + template + bool startswidth(T1 const& prefix, T2 const& start, T3 const& end) const + { + return this->startswidth(object(prefix), object(start), object(end)); + } + + BOOST_PYTHON_DECL str strip() const ; + BOOST_PYTHON_DECL str swapcase() const ; + BOOST_PYTHON_DECL str title() const ; + + BOOST_PYTHON_DECL str translate(object_cref table) const; + + template + str translate(T const& table) const + { + return this->translate(object(table)); + } + + BOOST_PYTHON_DECL str translate(object_cref table, object_cref deletechars) const; + + template + str translate(T1 const& table, T2 const& deletechars) const + { + return this->translate(object(table), object(deletechars)); + } + + BOOST_PYTHON_DECL str upper() const; + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(str) + + private: + static BOOST_PYTHON_DECL detail::new_reference call(object const&); +}; + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits + : pytype_object_manager_traits<&PyString_Type,str> + { + }; +} + +}} // namespace boost::python + +#endif // STR_20020703_HPP diff --git a/include/boost/python/tag.hpp b/include/boost/python/tag.hpp new file mode 100644 index 00000000..c8ce6878 --- /dev/null +++ b/include/boost/python/tag.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2002. 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 TAG_DWA2002720_HPP +# define TAG_DWA2002720_HPP + +namespace boost { namespace python { + +// used only to prevent argument-dependent lookup from finding the +// wrong function in some cases. Cheaper than qualification. +enum tag_t { tag }; + +}} // namespace boost::python + +#endif // TAG_DWA2002720_HPP diff --git a/include/boost/python/to_python_converter.hpp b/include/boost/python/to_python_converter.hpp new file mode 100644 index 00000000..814b9ba7 --- /dev/null +++ b/include/boost/python/to_python_converter.hpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_CONVERTER_DWA200221_HPP +# define TO_PYTHON_CONVERTER_DWA200221_HPP + +# include +# include +# include + +namespace boost { namespace python { + +template +struct to_python_converter +{ + to_python_converter(); +}; + +// +// implementation +// + +template +to_python_converter::to_python_converter() +{ + typedef converter::as_to_python_function< + T, Conversion + > normalized; + + converter::registry::insert( + &normalized::convert + , type_id()); +} + +}} // namespace boost::python + +#endif // TO_PYTHON_CONVERTER_DWA200221_HPP diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp new file mode 100644 index 00000000..23ff8594 --- /dev/null +++ b/include/boost/python/to_python_indirect.hpp @@ -0,0 +1,118 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_INDIRECT_DWA200221_HPP +# define TO_PYTHON_INDIRECT_DWA200221_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +template +struct to_python_indirect +{ + static bool convertible(); + PyObject* operator()(T ptr) const; + private: + static PyTypeObject* type(); +}; + +// +// implementations +// +namespace detail +{ + struct make_owning_holder + { + typedef PyObject* result_type; + template + static result_type execute(T* p) + { + // can't use auto_ptr with Intel 5 for some reason +# if defined(__ICL) && __ICL < 600 + typedef boost::shared_ptr smart_pointer; +# else + typedef std::auto_ptr smart_pointer; +# endif + typedef objects::pointer_holder holder_t; + + smart_pointer ptr(p); + return objects::make_instance::execute(ptr); + } + }; + + struct make_reference_holder + { + typedef PyObject* result_type; + template + static result_type execute(T* p) + { + typedef objects::pointer_holder holder_t; + return objects::make_instance::execute(p); + } + }; + + struct get_pointer_class + { + typedef PyTypeObject* result_type; + template + static result_type execute(T* p) + { + BOOST_STATIC_ASSERT(is_class::value); + return converter::registered::converters.class_object; + } + }; + + // null_pointer_to_none -- return none() for null pointers and 0 for all other types/values + // + // Uses simulated partial ordering + template + inline PyObject* null_pointer_to_none(T&, int) + { + return 0; + } + + // overload for pointers + template + inline PyObject* null_pointer_to_none(T* x, long) + { + return x == 0 ? python::detail::none() : 0; + } +} + +template +inline bool to_python_indirect::convertible() +{ + BOOST_STATIC_ASSERT(is_pointer::value || is_reference::value); + return type() != 0; +} + +template +inline PyObject* to_python_indirect::operator()(T x) const +{ + PyObject* const null_result = detail::null_pointer_to_none(x, 1L); + if (null_result != 0) + return null_result; + + return detail::unwind_type(x); +} + +template +inline PyTypeObject* to_python_indirect::type() +{ + return detail::unwind_type(); +} + +}} // namespace boost::python + +#endif // TO_PYTHON_INDIRECT_DWA200221_HPP diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp new file mode 100644 index 00000000..b85eaf68 --- /dev/null +++ b/include/boost/python/to_python_value.hpp @@ -0,0 +1,96 @@ +// Copyright David Abrahams 2002. 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 TO_PYTHON_VALUE_DWA200221_HPP +# define TO_PYTHON_VALUE_DWA200221_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct object_manager_to_python_value + { + typedef typename add_reference< + typename add_const::type + >::type argument_type; + + static bool convertible(); + PyObject* operator()(argument_type) const; + }; + + + template + struct registry_to_python_value + { + typedef typename add_reference< + typename add_const::type + >::type argument_type; + + static bool convertible(); + PyObject* operator()(argument_type) const; + }; +} + +template +struct to_python_value + : mpl::select_type< + boost::type_traits::ice_or< + converter::is_object_manager::value + , converter::is_reference_to_object_manager::value + >::value + + , detail::object_manager_to_python_value + , detail::registry_to_python_value + >::type +{ +}; + +// +// implementation +// +namespace detail +{ + template + inline bool registry_to_python_value::convertible() + { + return converter::registered::converters.to_python != 0; + } + + template + inline PyObject* registry_to_python_value::operator()(argument_type x) const + { + return converter::registered::converters.to_python(&x); + } + + template + inline bool object_manager_to_python_value::convertible() + { + return true; + } + + template + inline PyObject* object_manager_to_python_value::operator()(argument_type x) const + { + return python::upcast( + python::xincref( + get_managed_object(x, tag)) + ); + } +} + +}} // namespace boost::python + +#endif // TO_PYTHON_VALUE_DWA200221_HPP diff --git a/include/boost/python/tuple.hpp b/include/boost/python/tuple.hpp new file mode 100644 index 00000000..38547696 --- /dev/null +++ b/include/boost/python/tuple.hpp @@ -0,0 +1,53 @@ +#ifndef TUPLE_20020706_HPP +#define TUPLE_20020706_HPP + +#include +#include + +namespace boost { namespace python { + +class tuple : public object +{ + public: + // tuple() -> an empty tuple + BOOST_PYTHON_DECL tuple(); + + // tuple(sequence) -> tuple initialized from sequence's items + BOOST_PYTHON_DECL tuple(object_cref sequence); + + template + explicit tuple(T const& sequence) + : object(tuple::call(object(sequence))) + { + } + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(tuple) + + private: + static BOOST_PYTHON_DECL detail::new_reference call(object const&); +}; + +// +// Converter Specializations // $$$ JDG $$$ moved here to prevent +// // G++ bug complaining specialization + // provided after instantiation +namespace converter +{ + template <> + struct object_manager_traits + : pytype_object_manager_traits<&PyTuple_Type,tuple> + { + }; +} + +// for completeness +inline tuple make_tuple() { return tuple(); } + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +}} // namespace boost::python + +#endif + diff --git a/include/boost/python/type_id.hpp b/include/boost/python/type_id.hpp new file mode 100755 index 00000000..cf818fe3 --- /dev/null +++ b/include/boost/python/type_id.hpp @@ -0,0 +1,134 @@ +// Copyright David Abrahams 2002. 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 TYPE_ID_DWA2002517_HPP +# define TYPE_ID_DWA2002517_HPP + +# include +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +// for this compiler at least, cross-shared-library type_info +// comparisons don't work, so use typeid(x).name() instead. It's not +// yet clear what the best default strategy is. +# if (defined(__GNUC__) && __GNUC__ >= 3) \ + || defined(_AIX) \ + || ( defined(__sgi) && defined(__host_mips)) +# define BOOST_PYTHON_TYPE_ID_NAME +# endif + +// type ids which represent the same information as std::type_info +// (i.e. the top-level reference and cv-qualifiers are stripped), but +// which works across shared libraries. +struct type_info : private totally_ordered +{ + inline type_info(std::type_info const& = typeid(void)); + + inline bool operator<(type_info const& rhs) const; + inline bool operator==(type_info const& rhs) const; + + char const* name() const; + friend BOOST_PYTHON_DECL std::ostream& operator<<( + std::ostream&, type_info const&); + + private: // data members +# ifdef BOOST_PYTHON_TYPE_ID_NAME + typedef char const* base_id_t; +# else + typedef std::type_info const* base_id_t; +# endif + + base_id_t m_base_type; +}; + +template +inline type_info type_id(boost::type* = 0) +{ + return type_info( +# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) + typeid(T) +# else // strip the decoration which msvc and Intel mistakenly leave in + python::detail::msvc_typeid() +# endif + ); +} + +# if defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 +// Older EDG-based compilers seems to mistakenly distinguish "int" from +// "signed int", etc., but only in typeid() expressions. However +// though int == signed int, the "signed" decoration is propagated +// 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)); \ +} + +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(short) +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(int) +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long) +// using Python's macro instead of Boost's - we don't seem to get the +// config right all the time. +# ifdef HAVE_LONG_LONG +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long long) +# endif +# undef BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID +# endif + + +inline type_info::type_info(std::type_info const& id) + : m_base_type( +# ifdef BOOST_PYTHON_TYPE_ID_NAME + id.name() +# else + &id +# endif + ) +{ +} + +inline bool type_info::operator<(type_info const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return std::strcmp(m_base_type, rhs.m_base_type) < 0; +# else + return m_base_type->before(*rhs.m_base_type); +# endif +} + +inline bool type_info::operator==(type_info const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return !std::strcmp(m_base_type, rhs.m_base_type); +# else + return *m_base_type == *rhs.m_base_type; +# endif +} + +inline char const* type_info::name() const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return m_base_type; +# else + return m_base_type->name(); +# endif +} + + +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&); + +}} // namespace boost::python + +#endif // TYPE_ID_DWA2002517_HPP diff --git a/include/boost/python/with_custodian_and_ward.hpp b/include/boost/python/with_custodian_and_ward.hpp new file mode 100644 index 00000000..4d022448 --- /dev/null +++ b/include/boost/python/with_custodian_and_ward.hpp @@ -0,0 +1,78 @@ +// Copyright David Abrahams 2002. 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 WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP +# define WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP + +# include +# include + +namespace boost { namespace python { + +template +struct with_custodian_and_ward : BasePolicy_ +{ + static bool precall(PyObject* args); +}; + +template +struct with_custodian_and_ward_postcall : BasePolicy_ +{ + static PyObject* postcall(PyObject* args, PyObject* result); +}; + +// +// implementations +// +template +bool with_custodian_and_ward::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 false; + PyObject* nurse = PyTuple_GetItem(args_, custodian - 1); + if (nurse == 0) return false; + + 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_XDECREF(life_support); + + return result; +} + +template +PyObject* with_custodian_and_ward_postcall::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 + +#endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 00000000..511408e8 --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,151 @@ +subproject libs/python/test ; + +# bring in the rules for python +SEARCH on python.jam = $(BOOST_BUILD_PATH) ; +include python.jam ; +# bring in rules for testing +SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; +include testing.jam ; + +local PYTHON_V1_PROPERTIES = $(PYTHON_PROPERTIES) ; +local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) ; + +# Convenience rule makes declaring tests faster +rule bpl-test ( name ? : files * ) +{ + files ?= $(name).py $(name).cpp ; + + local modules ; + local py ; + for local f in $(files) + { + if $(f:S) = .py + { + if $(py) + { + EXIT too many python drivers specified: "$(py)" "$(f)" ; + } + py = $(f) ; + } + } + + name ?= $(py:S=) ; + + for local f in $(files) + { + if $(f:S) != .py + { + local m = $(f:S=) ; + + if $(m) = $(py:S=) + { + m = $(name) ; + + if $(m) = $(py:S=) + { + m = $(m)_ext ; + } + } + extension $(m) : $(f) ../bpl ; + modules += $(m) ; + } + } + + boost-python-runtest $(name) : $(py) $(modules) ; +} + +bpl-test enum ; +bpl-test minimal ; +bpl-test docstring ; +bpl-test exception_translator ; +bpl-test pearu1 : test_cltree.py cltree.cpp ; +bpl-test try : newtest.py m1.cpp m2.cpp ; +bpl-test builtin_converters : test_builtin_converters.py test_builtin_converters.cpp ; +bpl-test test_pointer_adoption ; +bpl-test operators ; +bpl-test callbacks ; +bpl-test defaults ; + +bpl-test object ; +bpl-test list ; +bpl-test long ; +bpl-test dict ; +bpl-test tuple ; +bpl-test str ; + +bpl-test virtual_functions ; +bpl-test back_reference ; +bpl-test implicit ; +bpl-test data_members ; + +bpl-test bienstman1 ; +bpl-test bienstman2 ; +bpl-test bienstman3 ; +bpl-test multi_arg_constructor ; +bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ; + +bpl-test extract ; + +bpl-test pickle1 ; +bpl-test pickle2 ; +bpl-test pickle3 ; + +bpl-test nested ; + +if $(TEST_BIENSTMAN_NON_BUGS) +{ + bpl-test bienstman4 ; + bpl-test bienstman5 ; +} + +# --- unit tests of library components --- + +local UNIT_TEST_PROPERTIES = + [ difference $(PYTHON_PROPERTIES) : BOOST_PYTHON_DYNAMIC_LIB ] BOOST_PYTHON_STATIC_LIB ; + +run indirect_traits_test.cpp ; +run destroy_test.cpp ; +run pointer_type_id_test.cpp ../../test/build/test_exec_monitor : : : $(UNIT_TEST_PROPERTIES) ; +run member_function_cast.cpp ; +run bases.cpp ; +run if_else.cpp ; +run pointee.cpp ; +run result.cpp ; + +compile string_literal.cpp ; +compile borrowed.cpp : $(UNIT_TEST_PROPERTIES) ; +compile object_manager.cpp : $(UNIT_TEST_PROPERTIES) ; + +run upcast.cpp ../../test/build/test_exec_monitor + : # command-line args + : # input files + : $(UNIT_TEST_PROPERTIES) + ; + +run select_holder.cpp ../../test/build/test_exec_monitor + : # command-line args + : # input files + : $(UNIT_TEST_PROPERTIES) + ; + + +run select_from_python_test.cpp ../src/converter/type_id.cpp ../../test/build/test_exec_monitor + : # command-line args + : # input files + : $(UNIT_TEST_PROPERTIES) + ; + +run select_arg_to_python_test.cpp ../src/converter/type_id.cpp ../../test/build/test_exec_monitor + : # command-line args + : # input files + : $(UNIT_TEST_PROPERTIES) + ; + +if $(TEST_EXPECTED_FAILURES) +{ + compile-fail ./raw_pyobject_fail1.cpp : $(PYTHON_PROPERTIES) ; + compile-fail ./raw_pyobject_fail2.cpp : $(PYTHON_PROPERTIES) ; + compile-fail ./object_fail1.cpp : $(PYTHON_PROPERTIES) ; +} + + diff --git a/test/back_reference.cpp b/test/back_reference.cpp new file mode 100644 index 00000000..73990640 --- /dev/null +++ b/test/back_reference.cpp @@ -0,0 +1,111 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include +#include +#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 +// specialized. +using namespace boost::python; + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + virtual ~X() { assert(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int x) { assert(magic == 7654321); this->x = x; } + int value() const { assert(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +int X::counter; + +struct Y : X +{ + Y(PyObject* self, int x) : X(x) {}; + Y(PyObject* self, Y const& rhs) : X(rhs), self(self) {}; + private: + Y(Y const&); + PyObject* self; +}; + +struct Z : X +{ + Z(PyObject* self, int x) : X(x) {}; + Z(PyObject* self, Z const& rhs) : X(rhs), self(self) {}; + private: + Z(Z const&); + PyObject* self; +}; + +Y const& copy_Y(Y const& y) { return y; } +Z const& copy_Z(Z const& z) { return z; } + +namespace boost { namespace python +{ + template <> + struct has_back_reference + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template <> + struct has_back_reference + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +}} + +// prove that back_references get initialized with the right PyObject* +object y_identity(back_reference y) +{ + return y.source(); +} + +// prove that back_references contain the right value +bool y_equality(back_reference y1, Y const& y2) +{ + return &y1.get() == &y2; +} + +BOOST_PYTHON_MODULE_INIT(back_reference_ext) +{ + def("copy_Y", copy_Y, return_value_policy()); + def("copy_Z", copy_Z, return_value_policy()); + def("x_instances", &X::count); + + class_("Y", args()) + .def("value", &Y::value) + .def("set", &Y::set) + ; + + class_ >("Z", args()) + .def("value", &Z::value) + .def("set", &Z::set) + ; + + def("y_identity", y_identity); + def("y_equality", y_equality); + +} + +#include "module_tail.cpp" diff --git a/test/bienstman1.cpp b/test/bienstman1.cpp new file mode 100644 index 00000000..b4acf059 --- /dev/null +++ b/test/bienstman1.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +struct A {}; + +struct V +{ + + virtual void f() = 0; + + const A* inside() {return &a;} + + A a; +}; + +const A* outside(const V& v) {return &v.a;} + +BOOST_PYTHON_MODULE_INIT(bienstman1_ext) +{ + using namespace boost::python; + using boost::shared_ptr; + using boost::python::return_value_policy; + using boost::python::reference_existing_object; + + class_ >("A"); + + class_("V", no_init) + .def("inside", &V::inside, + return_value_policy()) + .def("outside", outside, + return_value_policy()) + ; +} + diff --git a/test/bienstman2.cpp b/test/bienstman2.cpp new file mode 100644 index 00000000..dd7ba532 --- /dev/null +++ b/test/bienstman2.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +struct C {}; + +struct D {}; + +struct E +{ + const D fe (const C&) {return D();} + const D fe2(const C&, const C&) {return D();} +}; + +BOOST_PYTHON_MODULE_INIT(bienstman2_ext) +{ + using namespace boost::python; + + class_("C"); + class_("D"); + class_("E") + .def("fe", &E::fe) // this compiles. + .def("fe2", &E::fe2) // this doesn't... well, now it does ;-) + ; +} diff --git a/test/bienstman3.cpp b/test/bienstman3.cpp new file mode 100644 index 00000000..f1dc212d --- /dev/null +++ b/test/bienstman3.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +struct V +{ + virtual void f() = 0; +}; + +struct B +{ + B(const V&) {} +}; + +BOOST_PYTHON_MODULE_INIT(bienstman3_ext) +{ + using namespace boost::python; + + class_("V", no_init); + class_("B", args()); + +} diff --git a/test/bienstman3.py b/test/bienstman3.py new file mode 100644 index 00000000..90efdd53 --- /dev/null +++ b/test/bienstman3.py @@ -0,0 +1,25 @@ +''' +>>> from bienstman3_ext import * + +>>> try: +... V() +... except RuntimeError, x: +... print x +... else: +... print 'expected an exception' +... +This class cannot be instantiated from Python + +''' +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 + sys.exit(run()[0]) diff --git a/test/callbacks.cpp b/test/callbacks.cpp new file mode 100644 index 00000000..700c190a --- /dev/null +++ b/test/callbacks.cpp @@ -0,0 +1,149 @@ +// Copyright David Abrahams 2002. 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 +#include +//#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::python; +BOOST_STATIC_ASSERT(converter::is_object_manager >::value); + +int apply_int_int(PyObject* f, int x) +{ + return call(f, x); +} + +void apply_void_int(PyObject* f, int x) +{ + call(f, x); +} + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + ~X() { assert(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int x) { assert(magic == 7654321); this->x = x; } + int value() const { assert(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +X apply_X_X(PyObject* f, X x) +{ + return call(f, x); +} + +void apply_void_X_ref(PyObject* f, X& x) +{ + call(f, boost::ref(x)); +} + +X& apply_X_ref_handle(PyObject* f, handle<> obj) +{ + return call(f, obj); +} + +X* apply_X_ptr_handle_cref(PyObject* f, handle<> const& obj) +{ + return call(f, obj); +} + +void apply_void_X_cref(PyObject* f, X const& x) +{ + call(f, boost::cref(x)); +} + +void apply_void_X_ptr(PyObject* f, X* x) +{ + call(f, ptr(x)); +} + +void apply_void_X_deep_ptr(PyObject* f, X* x) +{ + call(f, x); +} + +char const* apply_cstring_cstring(PyObject* f, char const* s) +{ + return call(f, s); +} + +char const* apply_cstring_pyobject(PyObject* f, PyObject* s) +{ + return call(f, borrowed(s)); +} + +char apply_char_char(PyObject* f, char c) +{ + return call(f, c); +} + +char const* apply_to_string_literal(PyObject* f) +{ + return call(f, "hello, world"); +} + +handle<> apply_to_own_type(handle<> x) +{ + // Tests that we can return handle<> from a callback and that we + // can pass arbitrary handle. + return call >(x.get(), type_handle(borrowed(x->ob_type))); +} + +object apply_object_object(PyObject* f, object x) +{ + return call(f, x); +} + +int X::counter; + +BOOST_PYTHON_MODULE_INIT(callbacks_ext) +{ + def("apply_object_object", apply_object_object); + def("apply_to_own_type", apply_to_own_type); + def("apply_int_int", apply_int_int); + def("apply_void_int", apply_void_int); + def("apply_X_X", apply_X_X); + def("apply_void_X_ref", apply_void_X_ref); + def("apply_void_X_cref", apply_void_X_cref); + def("apply_void_X_ptr", apply_void_X_ptr); + def("apply_void_X_deep_ptr", apply_void_X_deep_ptr); + + def("apply_X_ptr_handle_cref", apply_X_ptr_handle_cref + , return_value_policy()); + + def("apply_X_ref_handle", apply_X_ref_handle + , return_value_policy()); + + def("apply_cstring_cstring", apply_cstring_cstring); + def("apply_cstring_pyobject", apply_cstring_pyobject); + def("apply_char_char", apply_char_char); + def("apply_to_string_literal", apply_to_string_literal); + + + class_("X", args()) + .def_init(args()) + .def("value", &X::value) + .def("set", &X::set) + ; + + def("x_count", &X::count); +} + +#include "module_tail.cpp" diff --git a/test/cltree.cpp b/test/cltree.cpp new file mode 100755 index 00000000..f7ea9eeb --- /dev/null +++ b/test/cltree.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +/* Non-modifiable definitions */ + +class basic { +public: + basic() { name = "cltree.basic"; } + std::string repr() { return name+"()"; } +protected: + std::string name; +}; + +class constant: public basic { +public: + constant() { name = "cltree.constant"; } +}; + +class symbol: public basic { +public: + symbol() { name = "cltree.symbol"; } +}; + +class variable: public basic { +public: + variable() { name = "cltree.variable"; } +}; + +/* EOF: Non-modifiable definitions */ + +class symbol_wrapper: public symbol { +public: + symbol_wrapper(PyObject* self): symbol() { + name = "cltree.wrapped_symbol"; + } +}; + +class variable_wrapper: public variable { +public: + variable_wrapper(PyObject* self): variable() { + name = "cltree.wrapped_variable"; + } + + // This constructor is introduced only because cannot use + // boost::noncopyable, see below. + variable_wrapper(PyObject* self,variable v): variable(v) {} + +}; + +BOOST_PYTHON_MODULE_INIT(cltree) +{ + boost::python::class_("basic") + .def("__repr__",&basic::repr) + ; + + boost::python::class_, boost::noncopyable>("constant") + ; + + + boost::python::class_("symbol") + ; + + boost::python::class_, variable_wrapper>("variable") + ; +} + +#include "module_tail.cpp" + diff --git a/test/data_members.cpp b/test/data_members.cpp new file mode 100644 index 00000000..99459dff --- /dev/null +++ b/test/data_members.cpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2002. 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 +#include +#include "test_class.hpp" + +#if defined(_AIX) && defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 +# include // works around a KCC intermediate code generation bug +#endif + + +using namespace boost::python; + +typedef test_class<> X; + +typedef test_class<1> Y; + +double get_fair_value(X const& x) { return x.value(); } + +BOOST_PYTHON_MODULE_INIT(data_members_ext) +{ + class_("X", args()) + .def("value", &X::value) + .def("set", &X::set) + .def_readonly("x", &X::x) + .add_property("fair_value", &get_fair_value) + ; + + class_("Y", args()) + .def("value", &Y::value) + .def("set", &Y::set) + .def_readwrite("x", &Y::x) + ; +} + +#include "module_tail.cpp" diff --git a/test/data_members.py b/test/data_members.py new file mode 100644 index 00000000..ab79a90a --- /dev/null +++ b/test/data_members.py @@ -0,0 +1,32 @@ +''' +>>> from data_members_ext import * +>>> x = X(42) +>>> x.x +42 +>>> try: x.x = 77 +... except AttributeError: pass +... else: print 'no error' + +>>> x.fair_value +42.0 + +>>> y = Y(69) +>>> y.x +69 +>>> y.x = 77 +>>> y.x +77 +''' + +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 + sys.exit(run()[0]) diff --git a/test/defaults.cpp b/test/defaults.cpp new file mode 100644 index 00000000..0f552666 --- /dev/null +++ b/test/defaults.cpp @@ -0,0 +1,187 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include +#include + +#if defined(_AIX) && defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 +# include // works around a KCC intermediate code generation bug +#endif + +using namespace boost::python; + +char const* const format = "int(%s); char(%s); string(%s); double(%s); "; + +/////////////////////////////////////////////////////////////////////////////// +// +// Overloaded functions +// +/////////////////////////////////////////////////////////////////////////////// +object +bar(int a, char b, std::string c, double d) +{ + return format % make_tuple(a, b, c, d); +} + +object +bar(int a, char b, std::string c) +{ + return format % make_tuple(a, b, c, 0.0); +} + +object +bar(int a, char b) +{ + return format % make_tuple(a, b, "default", 0.0); +} + +object +bar(int a) +{ + return format % make_tuple(a, 'D', "default", 0.0); +} + +BOOST_PYTHON_FUNCTION_OVERLOADS(bar_stubs, bar, 1, 4) + +/////////////////////////////////////////////////////////////////////////////// +// +// Functions with default arguments +// +/////////////////////////////////////////////////////////////////////////////// +object +foo(int a, char b = 'D', std::string c = "default", double d = 0.0) +{ + return format % make_tuple(a, b, c, d); +} + +BOOST_PYTHON_FUNCTION_OVERLOADS(foo_stubs, foo, 1, 4) + +/////////////////////////////////////////////////////////////////////////////// +// +// Overloaded member functions with default arguments +// +/////////////////////////////////////////////////////////////////////////////// +struct Y { + + Y() {} + + object + get_state() const + { + return format % make_tuple(a, b, c, d); + } + + int a; char b; std::string c; double d; +}; + + +struct X { + + X() {} + + X(int a, char b = 'D', std::string c = "constructor", double d = 0.0) + : state(format % make_tuple(a, b, c, d)) + {} + + X(std::string s, bool b) + : state("Got exactly two arguments from constructor: string(%s); bool(%s); " % make_tuple(s, b)) + {} + + object + bar(int a, char b = 'D', std::string c = "default", double d = 0.0) const + { + return format % make_tuple(a, b, c, d); + } + + Y const& + bar2(int a = 0, char b = 'D', std::string c = "default", double d = 0.0) + { + // tests zero arg member function and return_internal_reference policy + y.a = a; + y.b = b; + y.c = c; + y.d = d; + return y; + } + + object + foo(int a, bool b=false) const + { + return "int(%s); bool(%s); " % make_tuple(a, b); + } + + object + foo(std::string a, bool b=false) const + { + return "string(%s); bool(%s); " % make_tuple(a, b); + } + + object + foo(list a, list b, bool c=false) const + { + return "list(%s); list(%s); bool(%s); " % make_tuple(a, b, c); + } + + object + get_state() const + { + return state; + } + + Y y; + object state; +}; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_bar_stubs, bar, 1, 4) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_bar_stubs2, bar2, 0, 4) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_foo_2_stubs, foo, 1, 2) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_foo_3_stubs, foo, 2, 3) + +/////////////////////////////////////////////////////////////////////////////// + +BOOST_PYTHON_MODULE_INIT(defaults_ext) +{ + def("foo", foo, foo_stubs()); + def("bar", (object(*)(int, char, std::string, double))0, bar_stubs()); + + // Show that this works with the old obsolete module version of def(). + module("defaults_ext") + .def("foobar", foo, foo_stubs()) + .def("barfoo", (object(*)(int, char, std::string, double))0, bar_stubs()) + ; + + class_("Y", no_init) + .def("get_state", &Y::get_state) + ; + + class_("X") + +# if (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600) + .def(init >()) + .def(init()) +# else + .def_init(args()) + .def_init(args()) + .def_init(args()) + .def_init(args()) + .def_init(args()) +# endif + .def("get_state", &X::get_state) + .def("bar", &X::bar, X_bar_stubs()) + .def("bar2", &X::bar2, X_bar_stubs2(), return_internal_reference<>()) + .def("foo", (object(X::*)(std::string, bool) const)0, X_foo_2_stubs()) + .def("foo", (object(X::*)(int, bool) const)0, X_foo_2_stubs()) + .def("foo", (object(X::*)(list, list, bool) const)0, X_foo_3_stubs()) + ; +} + +#include "module_tail.cpp" + diff --git a/test/defaults.py b/test/defaults.py new file mode 100644 index 00000000..aa7602f2 --- /dev/null +++ b/test/defaults.py @@ -0,0 +1,130 @@ +""" + +>>> from defaults_ext import * +>>> bar(1) +'int(1); char(D); string(default); double(0.0); ' +>>> bar(2, 'X') +'int(2); char(X); string(default); double(0.0); ' +>>> bar(3, 'Y', "Hello World") +'int(3); char(Y); string(Hello World); double(0.0); ' +>>> bar(4, 'Z', "Hi There", 3.3) +'int(4); char(Z); string(Hi There); double(3.3); ' +>>> foo(1) +'int(1); char(D); string(default); double(0.0); ' +>>> foo(2, 'X') +'int(2); char(X); string(default); double(0.0); ' +>>> foo(3, 'Y', "Hello World") +'int(3); char(Y); string(Hello World); double(0.0); ' +>>> foo(4, 'Z', "Hi There", 3.3) +'int(4); char(Z); string(Hi There); double(3.3); ' +>>> x = X() +>>> x.bar(1) +'int(1); char(D); string(default); double(0.0); ' +>>> x.bar(2, 'X') +'int(2); char(X); string(default); double(0.0); ' +>>> x.bar(3, 'Y', "Hello World") +'int(3); char(Y); string(Hello World); double(0.0); ' +>>> x.bar(4, 'Z', "Hi There", 3.3) +'int(4); char(Z); string(Hi There); double(3.3); ' +>>> x.foo(5) +'int(5); bool(0); ' +>>> x.foo(6, 0) +'int(6); bool(0); ' +>>> x.foo(7, 1) +'int(7); bool(1); ' +>>> x.foo("A") +'string(A); bool(0); ' +>>> x.foo("B", False) +'string(B); bool(0); ' +>>> x.foo("C", True) +'string(C); bool(1); ' +>>> x.foo([0,1,2], [2,3,4]) +'list([0, 1, 2]); list([2, 3, 4]); bool(0); ' +>>> x.foo([0,1,2], [2,3,4], False) +'list([0, 1, 2]); list([2, 3, 4]); bool(0); ' +>>> x.foo([0,1,2], [2,3,4], True) +'list([0, 1, 2]); list([2, 3, 4]); bool(1); ' +>>> x = X(1) +>>> x.get_state() +'int(1); char(D); string(constructor); double(0.0); ' +>>> x = X(1, 'X') +>>> x.get_state() +'int(1); char(X); string(constructor); double(0.0); ' +>>> x = X(1, 'X', "Yabadabadoo") +>>> x.get_state() +'int(1); char(X); string(Yabadabadoo); double(0.0); ' +>>> x = X(1, 'X', "Phoenix", 3.65) +>>> x.get_state() +'int(1); char(X); string(Phoenix); double(3.65); ' +>>> x.bar2().get_state() +'int(0); char(D); string(default); double(0.0); ' +>>> x.bar2(1).get_state() +'int(1); char(D); string(default); double(0.0); ' +>>> x.bar2(1, 'K').get_state() +'int(1); char(K); string(default); double(0.0); ' +>>> x.bar2(1, 'K', "Kim").get_state() +'int(1); char(K); string(Kim); double(0.0); ' +>>> x.bar2(1, 'K', "Kim", 9.9).get_state() +'int(1); char(K); string(Kim); double(9.9); ' +>>> x = X("Phoenix", 1) +>>> x.get_state() +'Got exactly two arguments from constructor: string(Phoenix); bool(1); ' + +""" +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 + sys.exit(run()[0]) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/destroy_test.cpp b/test/destroy_test.cpp new file mode 100644 index 00000000..38d5d1d5 --- /dev/null +++ b/test/destroy_test.cpp @@ -0,0 +1,81 @@ +#include +#include + +struct bar; + +namespace boost +{ + // lie to the library about bar so we can show that its destructor is optimized away. + template <> + struct has_trivial_destructor + { + BOOST_STATIC_CONSTANT(bool, value=true); + }; +} + + +int count; +int marks[] = { + -1 + , -1, -1 + , -1, -1, -1, -1 + , -1 +}; +int* kills = marks; + +struct foo +{ + foo() : n(count++) {} + ~foo() + { + *kills++ = n; + } + int n; +}; + +struct bar : foo {}; + +void assert_destructions(int n) +{ + for (int i = 0; i < n; ++i) + assert(marks[i] == i); + assert(marks[n] == -1); +} + +int main() +{ + assert_destructions(0); + typedef int a[2]; + + foo* f1 = new foo; + boost::python::detail::destroy_referent(f1); + assert_destructions(1); + + foo* f2 = new foo[2]; + typedef foo x[2]; + + boost::python::detail::destroy_referent(f2); + assert_destructions(3); + + typedef foo y[2][2]; + x* f3 = new y; + boost::python::detail::destroy_referent(f3); + assert_destructions(7); + + bar* b1 = new bar; + boost::python::detail::destroy_referent(b1); + assert_destructions(7); + + bar* b2 = new bar[2]; + typedef bar xb[2]; + + boost::python::detail::destroy_referent(b2); + assert_destructions(7); + + typedef bar yb[2][2]; + xb* b3 = new yb; + boost::python::detail::destroy_referent(b3); + assert_destructions(7); + + return 0; +} diff --git a/test/dict.cpp b/test/dict.cpp new file mode 100644 index 00000000..0850c6be --- /dev/null +++ b/test/dict.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include + +using namespace boost::python; + +object new_dict() +{ + return dict(); +} + +object data_dict() +{ + dict tmp1; + tmp1["key1"] = "value1"; + + dict tmp2; + tmp2["key2"] = "value2"; + tmp1[1] = tmp2; + return tmp1; +} + +object dict_from_sequence(object sequence) +{ + return dict(sequence); +} + +object dict_keys(dict data) +{ + return data.keys(); +} + +object dict_values(dict data) +{ + return data.values(); +} + +object dict_items(dict data) +{ + return data.items(); +} + +void work_with_dict(dict data1, dict data2) +{ + if (!data1.has_key("k1")) { + throw std::runtime_error("dict does not have key 'k1'"); + } + data1.update(data2); +} + +void test_templates(object print) +{ + std::string key = "key"; + + dict tmp; + tmp[1] = "a test string"; + print(tmp.get(1)); + //print(tmp[1]); + tmp[1.5] = 13; + print(tmp.get(1.5)); + print(tmp); + print(tmp.get(2,"default")); + print(tmp.has_key(key)); + print(tmp.setdefault(3,"default")); + //print(tmp[3]); +} + +BOOST_PYTHON_MODULE_INIT(dict_ext) +{ + def("new_dict", new_dict); + def("data_dict", data_dict); + def("dict_keys", dict_keys); + def("dict_values", dict_values); + def("dict_items", dict_items); + def("dict_from_sequence", dict_from_sequence); + def("work_with_dict", work_with_dict); + def("test_templates", test_templates); +} diff --git a/test/dict.py b/test/dict.py new file mode 100644 index 00000000..fdabf2c9 --- /dev/null +++ b/test/dict.py @@ -0,0 +1,40 @@ +""" +>>> from dict_ext import * +>>> def printer(*args): +... for x in args: print x, +... print +... +>>> print new_dict() +{} +>>> print data_dict() +{1: {'key2': 'value2'}, 'key1': 'value1'} +>>> tmp = data_dict() +>>> print dict_keys(tmp) +[1, 'key1'] +>>> print dict_values(tmp) +[{'key2': 'value2'}, 'value1'] +>>> print dict_items(tmp) +[(1, {'key2': 'value2'}), ('key1', 'value1')] +>>> print dict_from_sequence([(1,1),(2,2),(3,3)]) +{1: 1, 2: 2, 3: 3} +>>> test_templates(printer) +a test string +13 +{1.5: 13, 1: 'a test string'} +default +0 +default +""" + +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 + sys.exit(run()[0]) diff --git a/test/docstring.cpp b/test/docstring.cpp new file mode 100644 index 00000000..01bacfba --- /dev/null +++ b/test/docstring.cpp @@ -0,0 +1,59 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include +#include +#include "test_class.hpp" + +// Just use math.h here; trying to use std::pow() causes too much +// trouble for non-conforming compilers and libraries. +#include + +using namespace boost::python; + +typedef test_class<> X; + +X* create(int x) +{ + return new X(x); +} + +unsigned long fact(unsigned long n) +{ + return n <= 1 ? n : n * fact(n - 1); +} + +BOOST_PYTHON_MODULE_INIT(docstring_ext) +{ + scope().attr("__doc__") = + "A simple test module for documentation strings\n" + "Exercised by docstring.py" + ; + + class_("X", + "A simple class wrapper around a C++ int\n" + "includes some error-checking" + + , args(), + "this is the __init__ function\n" + "its documentation has two lines." + + ) + .def("value", &X::value, + "gets the value of the object") + ; + + def("create", create, return_value_policy(), + "creates a new X object"); + + def("fact", fact, "compute the factorial"); +} + +#include "module_tail.cpp" diff --git a/test/docstring.py b/test/docstring.py new file mode 100644 index 00000000..15cfdaf1 --- /dev/null +++ b/test/docstring.py @@ -0,0 +1,54 @@ +''' +>>> from docstring_ext import * + +>>> def printdoc(x): +... print x.__doc__ + +>>> printdoc(X) +A simple class wrapper around a C++ int +includes some error-checking + +>>> printdoc(X.__init__) +this is the __init__ function +its documentation has two lines. + +>>> printdoc(X.value) +gets the value of the object + +>>> printdoc(create) +creates a new X object + +>>> printdoc(fact) +compute the factorial +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + + import docstring_ext + + result = doctest.testmod(sys.modules.get(__name__)) + + import pydoc + import re + docmodule = lambda m: re.sub(".\10", "", pydoc.text.docmodule(m)) + try: + print 'printing module help:' + print docmodule(docstring_ext) + except object, x: + print '********* failed **********' + print x + result = list(result) + result[0] += 1 + return tuple(result) + + return result + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) diff --git a/test/enum.cpp b/test/enum.cpp new file mode 100644 index 00000000..d6147bc0 --- /dev/null +++ b/test/enum.cpp @@ -0,0 +1,27 @@ +// Copyright David Abrahams 2002. 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 +#include +#include + +using namespace boost::python; + +enum color { red = 1, green = 2, blue = 4 }; + +color identity_(color x) { return x; } + +BOOST_PYTHON_MODULE_INIT(enum_ext) +{ + enum_("color") + .value("red", red) + .value("green", green) + .value("blue", blue) + ; + + def("identity", identity_); +} + +#include "module_tail.cpp" diff --git a/test/enum.py b/test/enum.py new file mode 100644 index 00000000..e21f8eb8 --- /dev/null +++ b/test/enum.py @@ -0,0 +1,42 @@ +''' +>>> from enum_ext import * + +>>> identity(color.red) +enum_ext.color.red + +>>> identity(color.green) +enum_ext.color.green + +>>> identity(color.blue) +enum_ext.color.blue + +>>> identity(color(1)) +enum_ext.color.red + +>>> identity(color(2)) +enum_ext.color.green + +>>> identity(color(3)) +enum_ext.color(3) + +>>> identity(color(4)) +enum_ext.color.blue + +>>> try: identity(1) +... except TypeError: pass +... else: print 'expected a TypeError' + +''' + +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 + sys.exit(run()[0]) diff --git a/test/exception_translator.cpp b/test/exception_translator.cpp new file mode 100644 index 00000000..8a6428fd --- /dev/null +++ b/test/exception_translator.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +struct error {}; + +void translate(error const& e) +{ + PyErr_SetString(PyExc_RuntimeError, "!!!error!!!"); +} + +void throw_error() +{ + throw error(); + +} + +BOOST_PYTHON_MODULE_INIT(exception_translator_ext) +{ + using namespace boost::python; + register_exception_translator(&translate); + + def("throw_error", throw_error); +} + diff --git a/test/exception_translator.py b/test/exception_translator.py new file mode 100644 index 00000000..78fe3507 --- /dev/null +++ b/test/exception_translator.py @@ -0,0 +1,22 @@ +''' +>>> from exception_translator_ext import * +>>> try: +... throw_error(); +... except RuntimeError, x: +... print x +... else: +... print 'Expected a RuntimeError!' +!!!error!!! +''' +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 + sys.exit(run()[0]) diff --git a/test/extract.cpp b/test/extract.cpp new file mode 100644 index 00000000..17640f2f --- /dev/null +++ b/test/extract.cpp @@ -0,0 +1,140 @@ +// Copyright David Abrahams 2002. 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 "test_class.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::python; + +typedef test_class<> X; + +bool extract_bool(object x) { return extract(x); } + +boost::python::list extract_list(object x) +{ + extract get_list((x)); + + // Make sure we always have the right idea about whether it's a list + bool is_list_1 = get_list.check(); + bool is_list_2 = PyObject_IsInstance(x.ptr(), (PyObject*)&PyList_Type); + assert(is_list_1 == is_list_2); + + return get_list(); +} + +char const* extract_cstring(object x) +{ + return extract(x); +} + +std::string extract_string(object x) +{ + std::string s = extract(x); + return s; +} + +std::string const& extract_string_cref(object x) +{ +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 +# pragma warning(push) +# pragma warning(disable:4172) // msvc lies about returning a reference to temporary +#elif defined(_MSC_VER) && defined(__ICL) && __ICL <= 600 +# pragma warning(push) +# pragma warning(disable:473) // intel/win32 does too +#endif + + return extract(x); + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(_MSC_VER) && defined(__ICL) && __ICL <= 600 +# pragma warning(pop) +#endif +} + +X extract_X(object x) +{ + return extract(x); +} + +X* extract_X_ptr(object x) { return extract(x); } + +X& extract_X_ref(object x) +{ + extract get_x(x); + return get_x; +} + +int double_X(object n) +{ + extract x(n); + return x().value() + x().value(); +} + +bool check_bool(object x) { return extract(x).check(); } +bool check_list(object x) { return extract(x).check(); } +bool check_cstring(object x) { return extract(x).check(); } +bool check_string(object x) { return extract(x).check(); } +bool check_string_cref(object x) { return extract(x).check(); } +bool check_X(object x) { return extract(x).check(); } +bool check_X_ptr(object x) { return extract(x).check(); } +bool check_X_ref(object x) { return extract(x).check(); } + +std::string x_rep(X const& x) +{ + return "X(" + boost::lexical_cast(x.value()) + ")"; +} + +BOOST_PYTHON_MODULE_INIT(extract_ext) +{ + implicitly_convertible(); + + def("extract_bool", extract_bool); + def("extract_list", extract_list); + def("extract_cstring", extract_cstring); + def("extract_string", extract_string); + def("extract_string_cref", extract_string_cref, return_value_policy()); + def("extract_X", extract_X); + def("extract_X_ptr", extract_X_ptr, return_value_policy()); + def("extract_X_ref", extract_X_ref, return_value_policy()); + + def("check_bool", check_bool); + def("check_list", check_list); + def("check_cstring", check_cstring); + def("check_string", check_string); + def("check_string_cref", check_string_cref); + def("check_X", check_X); + def("check_X_ptr", check_X_ptr); + def("check_X_ref", check_X_ref); + + def("double_X", double_X); + + def("count_Xs", &X::count); + ; + + object x_class( + class_("X", args()) + .def( "__repr__", x_rep)); + + // Instantiate an X object through the Python interface + object x_obj = x_class(3); + + // Get the C++ object out of the Python object + X const& x = extract(x_obj); + assert(x.value() == 3); +} + + +#include "module_tail.cpp" + diff --git a/test/extract.py b/test/extract.py new file mode 100644 index 00000000..328049dd --- /dev/null +++ b/test/extract.py @@ -0,0 +1,102 @@ +''' + >>> from extract_ext import * + +Just about anything has a truth value in Python + + >>> assert check_bool(None) + >>> extract_bool(None) + 0 + + >>> assert check_bool(2) + >>> extract_bool(2) + 1 + + >>> assert not check_bool('') + +Check that object manager types work properly. These are a different +case because they wrap Python objects instead of being wrapped by them. + + >>> assert not check_list(2) + >>> try: x = extract_list(2) + ... except TypeError, x: + ... if str(x) != 'Expecting an object of type list; got an object of type int instead': + ... print x + ... else: + ... print 'expected an exception, got', x, 'instead' + +Can't extract a list from a tuple. Use list(x) to convert a sequence +to a list: + + >>> assert not check_list((1, 2, 3)) + >>> assert check_list([1, 2, 3]) + >>> extract_list([1, 2, 3]) + [1, 2, 3] + +Can get a char const* from a Python string: + + >>> assert check_cstring('hello') + >>> extract_cstring('hello') + 'hello' + +Can't get a char const* from a Python int: + + >>> assert not check_cstring(1) + >>> try: x = extract_cstring(1) + ... except TypeError: pass + ... else: + ... print 'expected an exception, got', x, 'instead' + +Extract an std::string (class) rvalue from a native Python type + + >>> assert check_string('hello') + >>> extract_string('hello') + 'hello' + +Constant references are not treated as rvalues for the purposes of +extract: + + >>> assert not check_string_cref('hello') + +We can extract lvalues where appropriate: + + >>> x = X(42) + >>> check_X(x) + 1 + >>> extract_X(x) + X(42) + + >>> check_X_ptr(x) + 1 + >>> extract_X_ptr(x) + X(42) + >>> extract_X_ref(x) + X(42) + +Demonstrate that double-extraction of an rvalue works, and all created +copies of the object are destroyed: + + >>> n = count_Xs() + >>> double_X(333) + 666 + >>> count_Xs() - n + 0 + +General check for cleanliness: + + >>> del x + >>> count_Xs() + 0 +''' + +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 + sys.exit(run()[0]) diff --git a/test/implicit.cpp b/test/implicit.cpp new file mode 100644 index 00000000..cbf34027 --- /dev/null +++ b/test/implicit.cpp @@ -0,0 +1,38 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include "test_class.hpp" + +using namespace boost::python; + +typedef test_class<> X; + +int x_value(X const& x) +{ + return x.value(); +} + +X make_x(int n) { return X(n); } + +BOOST_PYTHON_MODULE_INIT(implicit_ext) +{ + implicitly_convertible(); + + def("x_value", x_value); + def("make_x", make_x); + + class_("X", args()) + .def("value", &X::value) + .def("set", &X::set) + ; + + implicitly_convertible(); +} + +#include "module_tail.cpp" diff --git a/test/input_iterator.cpp b/test/input_iterator.cpp new file mode 100644 index 00000000..19b50f77 --- /dev/null +++ b/test/input_iterator.cpp @@ -0,0 +1,49 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include + +using namespace boost::python; + +typedef std::list list_int; + +// Prove that we can handle InputIterators which return rvalues. +struct doubler +{ + typedef int result_type; + int operator()(int x) const { return x * 2; } +}; + +typedef boost::transform_iterator_generator::type doubling_iterator; +typedef std::pair list_range2; + +list_range2 range2(list_int& x) +{ + return list_range2( + boost::make_transform_iterator(x.begin(), doubler()) + , boost::make_transform_iterator(x.end(), doubler())); +} + +// We do this in a separate module from iterators_ext (iterators.cpp) +// to work around an MSVC6 linker bug, which causes it to complain +// about a "duplicate comdat" if the input iterator is instantiated in +// the same module with the others. +BOOST_PYTHON_MODULE_INIT(input_iterator) +{ + def("range2", &::range2); + + class_("list_range2") + // We can wrap InputIterators which return by-value + .def("__iter__" + , range(&list_range2::first, &list_range2::second)) + ; +} + +#include "module_tail.cpp" diff --git a/test/iterator.cpp b/test/iterator.cpp new file mode 100644 index 00000000..7aaae77c --- /dev/null +++ b/test/iterator.cpp @@ -0,0 +1,124 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::python; + +typedef std::list list_int; +typedef std::list list_list; + + +void push_back(list_int& x, int y) +{ + x.push_back(y); +} + +void push_list_back(list_list& x, list_int const& y) +{ + x.push_back(y); +} + +int back(list_int& x) +{ + return x.back(); +} + +typedef std::pair list_range; + +list_range range(list_int& x) +{ + return list_range(x.begin(), x.end()); +} + +struct two_lists +{ + two_lists() + { + int primes[] = { 2, 3, 5, 7, 11, 13 }; + std::copy(primes, primes + sizeof(primes)/sizeof(*primes), std::back_inserter(one)); + int evens[] = { 2, 4, 6, 8, 10, 12 }; + std::copy(evens, evens + sizeof(evens)/sizeof(*evens), std::back_inserter(two)); + } + + struct two_start + { + typedef list_int::iterator result_type; + result_type operator()(two_lists& ll) const { return ll.two.begin(); } + }; + friend struct two_start; + + list_int::iterator one_begin() { return one.begin(); } + list_int::iterator two_begin() { return two.begin(); } + + list_int::iterator one_end() { return one.end(); } + list_int::iterator two_end() { return two.end(); } + +private: + list_int one; + list_int two; +}; + +BOOST_PYTHON_MODULE_INIT(iterator_ext) +{ + def("range", &::range); + + class_("list_int") + .def("push_back", push_back) + .def("back", back) + .def("__iter__", iterator()) + ; + + class_("list_range") + + // We can specify data members + .def("__iter__" + , range(&list_range::first, &list_range::second)) + ; + + class_("two_lists") + + // We can spcify member functions + .add_property( + "primes" + , range(&two_lists::one_begin, &two_lists::one_end)) + + // Prove that we can explicitly specify call policies + .add_property( + "evens" + , range >( + &two_lists::two_begin, &two_lists::two_end)) + + // Prove that we can specify call policies and target + .add_property( + "twosies" + , range, two_lists>( + // And we can use adaptable function objects when + // partial specialization is available. +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + two_lists::two_start() +# else + &two_lists::two_begin +# endif + , &two_lists::two_end)) + ; + + class_("list_list") + .def("push_back", push_list_back) + .def("__iter__", iterator >()) + ; +} + +#include "module_tail.cpp" diff --git a/test/list.cpp b/test/list.cpp new file mode 100644 index 00000000..b3bce4a2 --- /dev/null +++ b/test/list.cpp @@ -0,0 +1,145 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include +#include "test_class.hpp" + +using namespace boost::python; + +object new_list() +{ + return list(); +} + +list listify(object x) +{ + return list(x); +} + +object listify_string(char const* s) +{ + return list(s); +} + +std::string x_rep(test_class<> const& x) +{ + return "X(" + boost::lexical_cast(x.value()) + ")"; +} + +object apply_object_list(object f, list x) +{ + return f(x); +} + +list apply_list_list(object f, list x) +{ + return call(f.ptr(), x); +} + +void append_object(list& x, object y) +{ + x.append(y); +} + +void append_list(list& x, list const& y) +{ + x.append(y); +} + +typedef test_class<> X; + +int notcmp(object const& x, object const& y) +{ + return y < x ? -1 : y > x ? 1 : 0; +} + +void exercise(list x, object y, object print) +{ + x.append(y); + x.append(5); + x.append(X(3)); + + print("after append:"); + print(x); + + print("number of", y, "instances:", x.count(y)); + + print("number of 5s:", x.count(5)); + + x.extend("xyz"); + print("after extend:"); + print(x); + print("index of", y, "is:", x.index(y)); + print("index of 'l' is:", x.index("l")); + + x.insert(4, 666); + print("after inserting 666:"); + print(x); + print("inserting with object as index:"); + x.insert(x[x.index(5)], "---"); + print(x); + + print("popping..."); + x.pop(); + print(x); + x.pop(x[x.index(5)]); + print(x); + x.pop(x.index(5)); + print(x); + + print("removing", y); + x.remove(y); + print(x); + print("removing", 666); + x.remove(666); + print(x); + + print("reversing..."); + x.reverse(); + print(x); + + print("sorted:"); + x.pop(2); // make sorting predictable + x.sort(); + print(x); + + print("reverse sorted:"); + x.sort(¬cmp); + print(x); + + list w; + w.append(5); + w.append(6); + w += "hi"; + assert(w[0] == 5); + assert(w[1] == 6); + assert(w[2] == 'h'); + assert(w[3] == 'i'); +} + +BOOST_PYTHON_MODULE_INIT(list_ext) +{ + def("new_list", new_list); + def("listify", listify); + def("listify_string", listify_string); + def("apply_object_list", apply_object_list); + def("apply_list_list", apply_list_list); + + def("append_object", append_object); + def("append_list", append_list); + + def("exercise", exercise); + + class_("X", args()) + .def( "__repr__", x_rep) + ; +} + diff --git a/test/list.py b/test/list.py new file mode 100644 index 00000000..0357b9a2 --- /dev/null +++ b/test/list.py @@ -0,0 +1,113 @@ +''' +>>> from list_ext import * + +>>> new_list() +[] + +>>> listify((1,2,3)) +[1, 2, 3] + +>>> letters = listify_string('hello') +>>> letters +['h', 'e', 'l', 'l', 'o'] + +>>> X(22) +X(22) + +>>> def identity(x): +... return x +>>> assert apply_object_list(identity, letters) is letters + + 5 is not convertible to a list + +>>> try: result = apply_object_list(identity, 5) +... except TypeError: pass +... else: print 'expected an exception, got', result, 'instead' + +>>> assert apply_list_list(identity, letters) is letters + + 5 is not convertible to a list as a return value + +>>> try: result = apply_list_list(len, letters) +... except TypeError: pass +... else: print 'expected an exception, got', result, 'instead' + +>>> append_object(letters, '.') +>>> letters +['h', 'e', 'l', 'l', 'o', '.'] + + tuples do not automatically convert to lists when passed as arguments + +>>> try: append_list(letters, (1,2)) +... except TypeError: pass +... else: print 'expected an exception' + +>>> append_list(letters, [1,2]) +>>> letters +['h', 'e', 'l', 'l', 'o', '.', [1, 2]] + + Check that subclass functions are properly called + +>>> class mylist(list): +... def append(self, o): +... list.append(self, o) +... if not hasattr(self, 'nappends'): +... self.nappends = 1 +... else: +... self.nappends += 1 +... +>>> l2 = mylist() +>>> append_object(l2, 'hello') +>>> append_object(l2, 'world') +>>> l2 +['hello', 'world'] +>>> l2.nappends +2 + +>>> def printer(*args): +... for x in args: print x, +... print +... + +>>> y = X(42) +>>> exercise(letters, y, printer) +after append: +['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(42), 5, X(3)] +number of X(42) instances: 1 +number of 5s: 1 +after extend: +['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y', 'z'] +index of X(42) is: 7 +index of 'l' is: 2 +after inserting 666: +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y', 'z'] +inserting with object as index: +['h', 'e', 'l', 'l', 666, '---', 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y', 'z'] +popping... +['h', 'e', 'l', 'l', 666, '---', 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y'] +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y'] +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(42), X(3), 'x', 'y'] +removing X(42) +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(3), 'x', 'y'] +removing 666 +['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(3), 'x', 'y'] +reversing... +['y', 'x', X(3), [1, 2], '.', 'o', 'l', 'l', 'e', 'h'] +sorted: +[[1, 2], '.', 'e', 'h', 'l', 'l', 'o', 'x', 'y'] +reverse sorted: +['y', 'x', 'o', 'l', 'l', 'h', 'e', '.', [1, 2]] +''' + +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 + sys.exit(run()[0]) diff --git a/test/long.cpp b/test/long.cpp new file mode 100644 index 00000000..32d3164a --- /dev/null +++ b/test/long.cpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include + +using namespace boost::python; + +object new_long() +{ + return long_(); +} + +long_ longify(object x) +{ + return long_(x); +} + +object longify_string(char const* s) +{ + return long_(s); +} + +char const* is_long1(long_& x) +{ + long_ y = x; + x += 50; + assert(x == y + 50); + return "yes"; +} + +int is_long2(char const*) +{ + return 0; +} + +BOOST_PYTHON_MODULE_INIT(long_ext) +{ + def("new_long", new_long); + def("longify", longify); + def("longify_string", longify_string); + def("is_long", is_long1); + def("is_long", is_long2); + ; +} + diff --git a/test/long.py b/test/long.py new file mode 100644 index 00000000..7d08e9b7 --- /dev/null +++ b/test/long.py @@ -0,0 +1,26 @@ +''' +>>> from long_ext import * +>>> new_long() +0L +>>> longify(42) +42L +>>> longify_string('300') +300L +>>> is_long(20L) +'yes' +>>> is_long('20') +0 +''' + +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 + sys.exit(run()[0]) diff --git a/test/m1.cpp b/test/m1.cpp new file mode 100644 index 00000000..f09e4a93 --- /dev/null +++ b/test/m1.cpp @@ -0,0 +1,268 @@ +// 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. + + +#include "simple_type.hpp" +#include "complicated.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Declare some straightforward extension types +extern "C" void +dealloc(PyObject* self) +{ + PyObject_Del(self); +} + +// Noddy is a type we got from one of the Python sample files +struct NoddyObject : PyObject +{ + int x; +}; + +PyTypeObject NoddyType = { + PyObject_HEAD_INIT(NULL) + 0, + "Noddy", + sizeof(NoddyObject), + 0, + dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +// Create a Noddy containing 42 +PyObject* new_noddy() +{ + NoddyObject* noddy = PyObject_New(NoddyObject, &NoddyType); + noddy->x = 42; + return (PyObject*)noddy; +} + +// Simple is a wrapper around a struct simple, which just contains a char* +struct SimpleObject +{ + PyObject_HEAD + simple x; +}; + +struct extract_simple_object +{ + static simple& execute(SimpleObject& o) { return o.x; } +}; + +PyTypeObject SimpleType = { + PyObject_HEAD_INIT(NULL) + 0, + "Simple", + sizeof(SimpleObject), + 0, + dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +// Create a Simple containing "hello, world" +PyObject* new_simple() +{ + SimpleObject* simple = PyObject_New(SimpleObject, &SimpleType); + simple->x.s = "hello, world"; + return (PyObject*)simple; +} + +// +// Declare some wrappers/unwrappers to test the low-level conversion +// mechanism. +// +using boost::python::to_python_converter; + +// Wrap a simple by copying it into a Simple +struct simple_to_python + : to_python_converter +{ + static PyObject* convert(simple const& x) + { + SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); + p->x = x; + return (PyObject*)p; + } +}; + +struct int_from_noddy +{ + static int& execute(NoddyObject& p) + { + return p.x; + } +}; + +// +// Some C++ functions to expose to Python +// + +// Returns the length of s's held string +int f(simple const& s) +{ + return strlen(s.s); +} + +int f_mutable_ref(simple& s) +{ + return strlen(s.s); +} + +int f_mutable_ptr(simple* s) +{ + return strlen(s->s); +} + +int f_const_ptr(simple const* s) +{ + return strlen(s->s); +} + +int f2(SimpleObject const& s) +{ + return strlen(s.x.s); +} + +// A trivial passthru function for simple objects +simple const& g(simple const& x) +{ + return x; +} + +struct A +{ + A() : x(0) {} + virtual ~A() {} + char const* name() { return "A"; } + int x; +}; + +struct B : A +{ + B() : x(1) {} + static char const* name(B*) { return "B"; } + int x; +}; + + +struct C : A +{ + C() : x(2) {} + char const* name() { return "C"; } + virtual ~C() {} + int x; +}; + +struct D : B, C +{ + D() : x(3) {} + char const* name() { return "D"; } + int x; +}; + +A take_a(A const& a) { return a; } +B take_b(B& b) { return b; } +C take_c(C* c) { return *c; } +D take_d(D* const& d) { return *d; } + +D take_d_shared_ptr(boost::shared_ptr d) { return *d; } + +boost::shared_ptr d_factory() { return boost::shared_ptr(new D); } + +BOOST_PYTHON_MODULE_INIT(m1) +{ + using namespace boost::python; + using boost::shared_ptr; + + simple_to_python(); + + lvalue_from_pytype(); + + lvalue_from_pytype< +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // doesn't support non-type member pointer parameters + extract_member +#else + extract_simple_object +#endif + , &SimpleType + >(); + + lvalue_from_pytype,&SimpleType>(); + + def("new_noddy", new_noddy); + def("new_simple", new_simple); + + // Expose f() in all its variations + def("f", f); + def("f_mutable_ref", f_mutable_ref); + def("f_mutable_ptr", f_mutable_ptr); + def("f_const_ptr", f_const_ptr); + + def("f2", f2); + + // Expose g() + def("g", g , return_value_policy() + ); + + def("take_a", take_a); + def("take_b", take_b); + def("take_c", take_c); + def("take_d", take_d); + + + def("take_d_shared_ptr", take_d_shared_ptr); + def("d_factory", d_factory); + + class_ >("A") + .def("name", &A::name) + ; + + // sequence points don't ensure that "A" is constructed before "B" + // or "C" below if we make them part of the same chain + class_, shared_ptr >("B") + .def("name", &B::name) + ; + + class_, shared_ptr >("C") + .def("name", &C::name) + ; + + class_, bases >("D") + .def("name", &D::name) + ; + + class_("complicated", + args()) + .def_init(args()) + .def("get_n", &complicated::get_n) + ; +} + +#include "module_tail.cpp" diff --git a/test/m2.cpp b/test/m2.cpp new file mode 100644 index 00000000..5eee1a89 --- /dev/null +++ b/test/m2.cpp @@ -0,0 +1,99 @@ +// 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. + +// This module exercises the converters exposed in m1 at a low level +// by exposing raw Python extension functions that use wrap<> and +// unwrap<> objects. +#include +#include +#include +#include +#include +#include "simple_type.hpp" + +// Get a simple (by value) from the argument, and return the +// string it holds. +PyObject* unwrap_simple(simple x) +{ + return PyString_FromString(x.s); +} + +// Likewise, but demands that its possible to get a non-const +// reference to the simple. +PyObject* unwrap_simple_ref(simple& x) +{ + return PyString_FromString(x.s); +} + +// Likewise, with a const reference to the simple object. +PyObject* unwrap_simple_const_ref(simple const& x) +{ + return PyString_FromString(x.s); +} + +// Get an int (by value) from the argument, and convert it to a +// Python Int. +PyObject* unwrap_int(int x) +{ + return PyInt_FromLong(x); +} + +// Get a non-const reference to an int from the argument +PyObject* unwrap_int_ref(int& x) +{ + return PyInt_FromLong(x); +} + +// Get a const reference to an int from the argument. +PyObject* unwrap_int_const_ref(int const& x) +{ + return PyInt_FromLong(x); +} + +// rewrap extracts a T from the argument, then converts the T back +// to a PyObject* and returns it. +template +struct rewrap +{ + static T f(T x) { return x; } +}; + +BOOST_PYTHON_MODULE_INIT(m2) +{ + using boost::python::return_value_policy; + using boost::python::copy_const_reference; + using boost::python::copy_non_const_reference; + using boost::python::def; + + def("unwrap_int", unwrap_int); + def("unwrap_int_ref", unwrap_int_ref); + def("unwrap_int_const_ref", unwrap_int_const_ref); + def("unwrap_simple", unwrap_simple); + def("unwrap_simple_ref", unwrap_simple_ref); + def("unwrap_simple_const_ref", unwrap_simple_const_ref); + + def("wrap_int", &rewrap::f); + + def("wrap_int_ref", &rewrap::f + , return_value_policy() + ); + + def("wrap_int_const_ref", &rewrap::f + , return_value_policy() + ); + + def("wrap_simple", &rewrap::f); + + def("wrap_simple_ref", &rewrap::f + , return_value_policy() + ); + + def("wrap_simple_const_ref", &rewrap::f + , return_value_policy() + ); +} + +#include "module_tail.cpp" diff --git a/test/minimal.cpp b/test/minimal.cpp new file mode 100644 index 00000000..be0fe6ec --- /dev/null +++ b/test/minimal.cpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2002. 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 +#include + +#if defined(_AIX) && defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 +# include // works around a KCC intermediate code generation bug +#endif + +BOOST_PYTHON_MODULE_INIT(minimal_ext) +{ +} + +#include "module_tail.cpp" diff --git a/test/multi_arg_constructor.cpp b/test/multi_arg_constructor.cpp new file mode 100644 index 00000000..43e8bfb1 --- /dev/null +++ b/test/multi_arg_constructor.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +struct A +{ + A(const double, const double, const double, const double, const double + , const double, const double + , const double, const double + ) {} +}; + +BOOST_PYTHON_MODULE_INIT(multi_arg_constructor_ext) +{ + using namespace boost::python; + using boost::shared_ptr; + + class_ >( + "A" + , args() + ) + ; + +} + diff --git a/test/nested.cpp b/test/nested.cpp new file mode 100644 index 00000000..9bc5be32 --- /dev/null +++ b/test/nested.cpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include "test_class.hpp" +#if __GNUC__ != 2 +# include +#else +# include +#endif + +typedef test_class<> X; +typedef test_class<1> Y; + +std::ostream& operator<<(std::ostream& s, X const& x) +{ + return s << x.value(); +} + +std::ostream& operator<<(std::ostream& s, Y const& x) +{ + return s << x.value(); +} + + +BOOST_PYTHON_MODULE_INIT(nested_ext) +{ + using namespace boost::python; + + // Establish X as the current scope. + scope x_class( + class_("X", args()) + .def(str(self)) + ); + + // Y will now be defined in the current scope + class_("Y", args()) + .def(str(self)) + ; +} + + +#include "module_tail.cpp" + + + diff --git a/test/nested.py b/test/nested.py new file mode 100644 index 00000000..97ac2a33 --- /dev/null +++ b/test/nested.py @@ -0,0 +1,35 @@ +''' + >>> from nested_ext import * + + >>> X + + + >>> X.__module__ + 'nested_ext' + + >>> X.__name__ + 'X' + + >>> X.Y + + + >>> X.Y.__module__ + 'nested_ext' + + >>> X.Y.__name__ + 'Y' + +''' + +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 + sys.exit(run()[0]) diff --git a/test/newtest.py b/test/newtest.py new file mode 100644 index 00000000..7b68a260 --- /dev/null +++ b/test/newtest.py @@ -0,0 +1,184 @@ +""" +>>> from m1 import * + +>>> from m2 import * + +>>> n = new_noddy() +>>> s = new_simple() +>>> unwrap_int(n) +42 +>>> unwrap_int_ref(n) +42 +>>> unwrap_int_const_ref(n) +42 +>>> unwrap_simple(s) +'hello, world' +>>> unwrap_simple_ref(s) +'hello, world' +>>> unwrap_simple_const_ref(s) +'hello, world' +>>> unwrap_int(5) +5 + +Can't get a non-const reference to a built-in integer object +>>> try: +... unwrap_int_ref(7) +... except: pass +... else: print 'no exception' + +>>> unwrap_int_const_ref(9) +9 + +>>> wrap_int(n) +42 + +try: wrap_int_ref(n) +... except: pass +... else: print 'no exception' + +>>> wrap_int_const_ref(n) +42 + +>>> unwrap_simple_ref(wrap_simple(s)) +'hello, world' + +>>> unwrap_simple_ref(wrap_simple_ref(s)) +'hello, world' + +>>> unwrap_simple_ref(wrap_simple_const_ref(s)) +'hello, world' + +>>> f(s) +12 + +>>> unwrap_simple(g(s)) +'hello, world' + +>>> f(g(s)) +12 + +>>> f_mutable_ref(g(s)) +12 + +>>> f_const_ptr(g(s)) +12 + +>>> f_mutable_ptr(g(s)) +12 + +>>> f2(g(s)) +12 + +Create an extension class which wraps "complicated" (init1 and get_n) +are a complicated constructor and member function, respectively. + +>>> c1 = complicated(s, 99) +>>> c1.get_n() +99 +>>> c2 = complicated(s) +>>> c2.get_n() +0 + + a quick regression test for a bug where None could be converted + to the target of any member function. To see it, we need to + access the __dict__ directly, to bypass the type check supplied + by the Method property which wraps the method when accessed as an + attribute. + +>>> try: A.__dict__['name'](None) +... except TypeError: pass +... else: print 'expected an exception!' + + +>>> a = A() +>>> b = B() +>>> c = C() +>>> d = D() + + +>>> take_a(a).name() +'A' + +>>> try: +... take_b(a) +... except: pass +... else: print 'no exception' + +>>> try: +... take_c(a) +... except: pass +... else: print 'no exception' + +>>> try: +... take_d(a) +... except: pass +... else: print 'no exception' + +------ +>>> take_a(b).name() +'A' + +>>> take_b(b).name() +'B' + +>>> try: +... take_c(b) +... except: pass +... else: print 'no exception' + +>>> try: +... take_d(b) +... except: pass +... else: print 'no exception' + +------- +>>> take_a(c).name() +'A' + +>>> try: +... take_b(c) +... except: pass +... else: print 'no exception' + +>>> take_c(c).name() +'C' + +>>> try: +... take_d(c) +... except: pass +... else: print 'no exception' + +------- +>>> take_a(d).name() +'A' +>>> take_b(d).name() +'B' +>>> take_c(d).name() +'C' +>>> take_d(d).name() +'D' + +>>> take_d_shared_ptr(d).name() +'D' + +>>> d_as_a = d_factory() +>>> dd = take_d(d_as_a) +>>> dd.name() +'D' + +""" + +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 + sys.exit(run()[0]) diff --git a/test/object.cpp b/test/object.cpp new file mode 100755 index 00000000..6a76aeb3 --- /dev/null +++ b/test/object.cpp @@ -0,0 +1,318 @@ +// Copyright David Abrahams 2002. 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 +#include +#include + +using namespace boost::python; + +object call_object_3(object f) +{ + return f(3); +} + +object message() +{ + return object("hello, world!"); +} + +object number() +{ + return object(42); +} + +object obj_getattr(object x, char const* name) +{ + return x.attr(name); +} + +object obj_const_getattr(object const& x, char const* name) +{ + return x.attr(name); +} + +void obj_setattr(object x, char const* name, object value) +{ + x.attr(name) = value; +} + +void obj_setattr42(object x, char const* name) +{ + x.attr(name) = 42; +} + +void obj_moveattr(object& x, char const* src, char const* dst) +{ + x.attr(dst) = x.attr(src); +} + +object obj_getitem(object x, object key) +{ + return x[key]; +} + +object obj_getitem3(object x) +{ + return x[3]; +} + +object obj_const_getitem(object const& x, object key) +{ + return x[key]; +} + +void obj_setitem(object x, object key, object value) +{ + x[key] = value; +} + +void obj_setitem42(object x, object key) +{ + x[key] = 42; +} + +void obj_moveitem(object& x, object src, object dst) +{ + x[dst] = x[src]; +} + +void obj_moveitem2(object const& x_src, object k_src, object& x_dst, object k_dst) +{ + x_dst[k_dst] = x_src[k_src]; +} + +bool test(object y) +{ + return y; +} + +bool test_not(object y) +{ + return !y; +} + +bool test_attr(object y, char* name) +{ + return y.attr(name); +} + +bool test_not_attr(object y, char* name) +{ + return !y.attr(name); +} + +bool test_item(object y, object key) +{ + return y[key]; +} + +bool test_not_item(object y, object key) +{ + return !y[key]; +} + +bool check_string_slice() +{ + object s("hello, world"); + + if (s.slice(_,-3) != "hello, wo") + return false; + + if (s.slice(-3,_) != "rld") + return false; + + if (", " != s.slice(5,7)) + return false; + + return s.slice(2,-1).slice(1,-1) == "lo, wor"; +} + +bool check_binary_operators() +{ + int y; + + object x(3); + +#define TEST_BINARY(op) \ + for (y = 1; y < 6; ++y) \ + { \ + if ((x op y) != (3 op y)) \ + return false; \ + } \ + for (y = 1; y < 6; ++y) \ + { \ + if ((y op x) != (y op 3)) \ + return false; \ + } \ + for (y = 1; y < 6; ++y) \ + { \ + object oy(y); \ + if ((oy op x) != (oy op 3)) \ + return false; \ + } + TEST_BINARY(>) + TEST_BINARY(>=) + TEST_BINARY(<) + TEST_BINARY(<=) + TEST_BINARY(==) + TEST_BINARY(!=) + + TEST_BINARY(+) + TEST_BINARY(-) + TEST_BINARY(*) + TEST_BINARY(/) + TEST_BINARY(%) + TEST_BINARY(<<) + TEST_BINARY(>>) + TEST_BINARY(&) + TEST_BINARY(^) + TEST_BINARY(|) + return true; +} + +bool check_inplace(object l, object o) +{ + int y; +#define TEST_INPLACE(op) \ + for (y = 1; y < 6; ++y) \ + { \ + object x(666); \ + x op##= y; \ + if (x != (666 op y)) \ + return false; \ + } \ + for (y = 1; y < 6; ++y) \ + { \ + object x(666); \ + x op##= object(y); \ + if (!(x == (666 op y))) \ + return false; \ + } + TEST_INPLACE(+) + TEST_INPLACE(-) + TEST_INPLACE(*) + TEST_INPLACE(/) + TEST_INPLACE(%) + TEST_INPLACE(<<) + TEST_INPLACE(>>) + TEST_INPLACE(&) + TEST_INPLACE(^) + TEST_INPLACE(|) + + l += l; + for (y = 0; y < 6; ++y) + { + if (l[y] != y % 3) + return false; + } + +#define TEST_ITEM_INPLACE(index, op, n, r1, r2) \ + l[index] op##= n; \ + if (l[index] != r1) \ + return false; \ + l[index] op##= object(n); \ + if (!(l[index] == r2)) \ + return false; + + TEST_ITEM_INPLACE(0,+,7,7,14) + TEST_ITEM_INPLACE(1,-,2,-1,-3) + TEST_ITEM_INPLACE(2,*,3,6,18) + TEST_ITEM_INPLACE(2,/,2,9,4) + TEST_ITEM_INPLACE(0,%,4,2,2) + l[0] += 1; + TEST_ITEM_INPLACE(0,<<,2,12,48) + TEST_ITEM_INPLACE(0,>>,1,24,12) + l[4] = 15; + TEST_ITEM_INPLACE(4,&,(16+4+1),5,5) + TEST_ITEM_INPLACE(0,^,1,13,12) + TEST_ITEM_INPLACE(0,|,1,13,13) + + o.attr("x0") = 0; + o.attr("x1") = 1; + o.attr("x2") = 2; + o.attr("x3") = 0; + o.attr("x4") = 1; + +#define TEST_ATTR_INPLACE(index, op, n, r1, r2) \ + o.attr("x" #index) op##= n; \ + if (o.attr("x" #index) != r1) \ + return false; \ + o.attr("x" #index) op##= object(n); \ + if (o.attr("x" #index) != r2) \ + return false; + + TEST_ATTR_INPLACE(0,+,7,7,14) + TEST_ATTR_INPLACE(1,-,2,-1,-3) + TEST_ATTR_INPLACE(2,*,3,6,18) + TEST_ATTR_INPLACE(2,/,2,9,4) + TEST_ATTR_INPLACE(0,%,4,2,2) + o.attr("x0") += 1; + TEST_ATTR_INPLACE(0,<<,2,12,48) + TEST_ATTR_INPLACE(0,>>,1,24,12) + o.attr("x4") = 15; + TEST_ATTR_INPLACE(4,&,(16+4+1),5,5) + TEST_ATTR_INPLACE(0,^,1,13,12) + TEST_ATTR_INPLACE(0,|,1,13,13) + + if (l[0] != o.attr("x0")) + return false; + if (l[1] != o.attr("x1")) + return false; + if (l[2] != o.attr("x2")) + return false; + if (l[3] != o.attr("x3")) + return false; + if (l[4] != o.attr("x4")) + return false; + + // set item 5 to be a list, by calling l.__class__ + l[5] = l.attr("__class__")(); + // append an element + l[5].attr("append")(2); + // Check its value + if (l[5][0] != 2) + return false; + + return true; +} + +BOOST_PYTHON_MODULE_INIT(object_ext) +{ + def("call_object_3", call_object_3); + def("message", message); + def("number", number); + + def("obj_getattr", obj_getattr); + def("obj_const_getattr", obj_const_getattr); + def("obj_setattr", obj_setattr); + def("obj_setattr42", obj_setattr42); + def("obj_moveattr", obj_moveattr); + + + def("obj_getitem", obj_getitem); + def("obj_getitem3", obj_getitem); + def("obj_const_getitem", obj_const_getitem); + def("obj_setitem", obj_setitem); + def("obj_setitem42", obj_setitem42); + def("obj_moveitem", obj_moveitem); + def("obj_moveitem2", obj_moveitem2); + + def("test", test); + def("test_not", test_not); + + def("test_attr", test_attr); + def("test_not_attr", test_not_attr); + + def("test_item", test_item); + def("test_not_item", test_not_item); + + def("check_binary_operators", check_binary_operators); + def("check_inplace", check_inplace); + def("check_string_slice", check_string_slice); + ; +} + +#include "module_tail.cpp" diff --git a/test/object_manager.cpp b/test/object_manager.cpp new file mode 100755 index 00000000..44005aeb --- /dev/null +++ b/test/object_manager.cpp @@ -0,0 +1,34 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include + +using namespace boost::python; +using namespace boost::python::converter; + +struct X {}; + +int main() +{ + BOOST_STATIC_ASSERT(is_object_manager >::value); + BOOST_STATIC_ASSERT(!is_object_manager::value); + BOOST_STATIC_ASSERT(!is_object_manager::value); + + BOOST_STATIC_ASSERT(is_reference_to_object_manager&>::value); + BOOST_STATIC_ASSERT(is_reference_to_object_manager const&>::value); + BOOST_STATIC_ASSERT(is_reference_to_object_manager volatile&>::value); + BOOST_STATIC_ASSERT(is_reference_to_object_manager const volatile&>::value); + + BOOST_STATIC_ASSERT(!is_reference_to_object_manager >::value); + BOOST_STATIC_ASSERT(!is_reference_to_object_manager::value); + BOOST_STATIC_ASSERT(!is_reference_to_object_manager::value); + BOOST_STATIC_ASSERT(!is_reference_to_object_manager::value); + + return 0; +} + diff --git a/test/operators.cpp b/test/operators.cpp new file mode 100755 index 00000000..e21b5509 --- /dev/null +++ b/test/operators.cpp @@ -0,0 +1,87 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include "test_class.hpp" +#if __GNUC__ != 2 +# include +#else +# include +#endif + +// Just use math.h here; trying to use std::pow() causes too much +// trouble for non-conforming compilers and libraries. +#include + +using namespace boost::python; + +typedef test_class<> X; + +X operator-(X const& l, X const& r) { return X(l.value() - r.value()); } +X operator-(int l, X const& r) { return X(l - r.value()); } +X operator-(X const& l, int r) { return X(l.value() - r); } + +X operator-(X const& x) { return X(-x.value()); } + +X& operator-=(X& l, X const& r) { l.set(l.value() - r.value()); return l; } + +bool operator<(X const& x, X const& y) { return x.value() < y.value(); } +bool operator<(X const& x, int y) { return x.value() < y; } +bool operator<(int x, X const& y) { return x < y.value(); } + +X abs(X x) { return X(x.value() < 0 ? -x.value() : x.value()); } + +X pow(X x, int y) +{ + return X(int(pow(double(x.value()), y))); +} + +X pow(X x, X y) +{ + return X(int(pow(double(x.value()), y.value()))); +} + +int pow(int x, X y) +{ + return int(pow(double(x), y.value())); +} + +std::ostream& operator<<(std::ostream& s, X const& x) +{ + return s << x.value(); +} + +BOOST_PYTHON_MODULE_INIT(operators_ext) +{ + class_("X", args()) + .def("value", &X::value) + .def(self - self) + .def(self - int()) + .def(other() - self) + .def(-self) + .def(self < other()) + .def(self < self) + .def(1 < self) + .def(self -= self) + .def(abs(self)) + .def(str(self)) + + .def(pow(self,self)) + .def(pow(self,int())) + .def(pow(int(),self)) + ; + + class_ >("Z", args()) + .def(int_(self)) + .def(float_(self)) + .def(complex_(self)) + ; +} + +#include "module_tail.cpp" diff --git a/test/pickle1.cpp b/test/pickle1.cpp new file mode 100644 index 00000000..e1397d60 --- /dev/null +++ b/test/pickle1.cpp @@ -0,0 +1,55 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below can be fully restored by passing the + appropriate argument to the constructor. Therefore it is sufficient + to define the pickle interface method __getinitargs__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include +#include +#include +#include + +#include + +namespace { + + // A friendly class. + class world + { + private: + std::string country; + public: + world(const std::string& country) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + }; + + struct world_pickle_suite : boost::python::pickle_suite + { + static + boost::python::tuple + getinitargs(const world& w) + { + using namespace boost::python; + return make_tuple(w.get_country()); + } + }; + +} + +BOOST_PYTHON_MODULE_INIT(pickle1_ext) +{ + using namespace boost::python; + class_("world", args()) + .def("greet", &world::greet) + .def_pickle(world_pickle_suite()) + ; +} diff --git a/test/pickle1.py b/test/pickle1.py new file mode 100644 index 00000000..d333919d --- /dev/null +++ b/test/pickle1.py @@ -0,0 +1,31 @@ +r'''>>> import pickle1_ext + >>> import pickle + >>> pickle1_ext.world.__module__ + 'pickle1_ext' + >>> pickle1_ext.world.__safe_for_unpickling__ + 1 + >>> pickle1_ext.world.__name__ + 'world' + >>> pickle1_ext.world('Hello').__reduce__() + (, ('Hello',)) + >>> wd = pickle1_ext.world('California') + >>> pstr = pickle.dumps(wd) + >>> wl = pickle.loads(pstr) + >>> print wd.greet() + Hello from California! + >>> print wl.greet() + Hello from California! +''' + +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 + sys.exit(run()[0]) diff --git a/test/pickle2.cpp b/test/pickle2.cpp new file mode 100644 index 00000000..984d6380 --- /dev/null +++ b/test/pickle2.cpp @@ -0,0 +1,99 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + For simplicity, the __dict__ is not included in the result of + __getstate__. This is not generally recommended, but a valid + approach if it is anticipated that the object's __dict__ will + always be empty. Note that safety guards are provided to catch + the cases where this assumption is not true. + + pickle3.cpp shows how to include the object's __dict__ in the + result of __getstate__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +#include +#include +#include +#include +#include + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + struct world_pickle_suite : boost::python::pickle_suite + { + static + boost::python::tuple + getinitargs(const world& w) + { + using namespace boost::python; + return make_tuple(w.get_country()); + } + + static + boost::python::tuple + getstate(const world& w) + { + using namespace boost::python; + return make_tuple(w.get_secret_number()); + } + + static + void + setstate(world& w, boost::python::tuple state) + { + using namespace boost::python; + if (len(state) != 1) + { + PyErr_SetObject(PyExc_ValueError, + ("expected 1-item tuple in call to __setstate__; got %s" + % state).ptr() + ); + throw_error_already_set(); + } + + long number = extract(state[0]); + if (number != 42) + w.set_secret_number(number); + } + }; + +} + +BOOST_PYTHON_MODULE_INIT(pickle2_ext) +{ + boost::python::class_( + "world", boost::python::args()) + .def("greet", &world::greet) + .def("get_secret_number", &world::get_secret_number) + .def("set_secret_number", &world::set_secret_number) + .def_pickle(world_pickle_suite()) + ; +} diff --git a/test/pickle2.py b/test/pickle2.py new file mode 100644 index 00000000..ec141bc9 --- /dev/null +++ b/test/pickle2.py @@ -0,0 +1,45 @@ +r'''>>> import pickle2_ext + >>> import pickle + >>> pickle2_ext.world.__module__ + 'pickle2_ext' + >>> pickle2_ext.world.__safe_for_unpickling__ + 1 + >>> pickle2_ext.world.__name__ + 'world' + >>> pickle2_ext.world('Hello').__reduce__() + (, ('Hello',), (0,)) + >>> for number in (24, 42): + ... wd = pickle2_ext.world('California') + ... wd.set_secret_number(number) + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number() + ... print wl.greet(), wl.get_secret_number() + Hello from California! 24 + Hello from California! 24 + Hello from California! 42 + Hello from California! 0 + +# Now show that the __dict__ is not taken care of. + >>> wd = pickle2_ext.world('California') + >>> wd.x = 1 + >>> wd.__dict__ + {'x': 1} + >>> try: pstr = pickle.dumps(wd) + ... except RuntimeError, err: print err[0] + ... + Incomplete pickle support (__getstate_manages_dict__ not set) +''' + +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 + sys.exit(run()[0]) diff --git a/test/pickle3.cpp b/test/pickle3.cpp new file mode 100644 index 00000000..8911b24c --- /dev/null +++ b/test/pickle3.cpp @@ -0,0 +1,107 @@ +// Example by Ralf W. Grosse-Kunstleve + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + The object's __dict__ is included in the result of __getstate__. + This requires more code (compare with pickle2.cpp), but is + unavoidable if the object's __dict__ is not always empty. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + struct world_pickle_suite : boost::python::pickle_suite + { + static + boost::python::tuple + getinitargs(const world& w) + { + using namespace boost::python; + return make_tuple(w.get_country()); + } + + static + boost::python::tuple + getstate(boost::python::object w_obj) + { + using namespace boost::python; + world const& w = extract(w_obj)(); + + return make_tuple(w_obj.attr("__dict__"), w.get_secret_number()); + } + + static + void + setstate(boost::python::object w_obj, boost::python::tuple state) + { + using namespace boost::python; + world& w = extract(w_obj)(); + + if (len(state) != 2) + { + PyErr_SetObject(PyExc_ValueError, + ("expected 2-item tuple in call to __setstate__; got %s" + % state).ptr() + ); + throw_error_already_set(); + } + + // restore the object's __dict__ + dict d = extract(w_obj.attr("__dict__"))(); + d.update(state[0]); + + // restore the internal state of the C++ object + long number = extract(state[1]); + if (number != 42) + w.set_secret_number(number); + } + + static bool getstate_manages_dict() { return true; } + }; + +} + +BOOST_PYTHON_MODULE_INIT(pickle3_ext) +{ + boost::python::class_( + "world", boost::python::args()) + .def("greet", &world::greet) + .def("get_secret_number", &world::get_secret_number) + .def("set_secret_number", &world::set_secret_number) + .def_pickle(world_pickle_suite()) + ; +} diff --git a/test/pickle3.py b/test/pickle3.py new file mode 100644 index 00000000..b700c1b0 --- /dev/null +++ b/test/pickle3.py @@ -0,0 +1,40 @@ +r'''>>> import pickle3_ext + >>> import pickle + >>> pickle3_ext.world.__module__ + 'pickle3_ext' + >>> pickle3_ext.world.__safe_for_unpickling__ + 1 + >>> pickle3_ext.world.__getstate_manages_dict__ + 1 + >>> pickle3_ext.world.__name__ + 'world' + >>> pickle3_ext.world('Hello').__reduce__() + (, ('Hello',), ({}, 0)) + >>> for number in (24, 42): + ... wd = pickle3_ext.world('California') + ... wd.set_secret_number(number) + ... wd.x = 2 * number + ... wd.y = 'y' * number + ... wd.z = 3. * number + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number(), wd.x, wd.y, wd.z + ... print wl.greet(), wl.get_secret_number(), wl.x, wl.y, wl.z + Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0 + Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0 + Hello from California! 42 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0 + Hello from California! 0 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0 +''' + +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 + sys.exit(run()[0]) diff --git a/test/select_arg_to_python_test.cpp b/test/select_arg_to_python_test.cpp new file mode 100644 index 00000000..df925a54 --- /dev/null +++ b/test/select_arg_to_python_test.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +// gcc 2.95.x and MIPSpro 7.3.1.3 linker seem to demand this definition +#if ((defined(__GNUC__) && __GNUC__ < 3)) \ + || (defined(__sgi) && defined(__EDG_VERSION__) && (__EDG_VERSION__ == 238)) +namespace boost { namespace python { +BOOST_PYTHON_DECL bool handle_exception_impl(function0) +{ + return true; +} +}} +#endif + +int result; + +#define ASSERT_SAME(T1,T2) \ + if (!is_same< T1, T2 >::value) { \ + std::cout << "*********************\n"; \ + std::cout << python::type_id< T1 >() << " != " << python::type_id< T2 >() << "\n"; \ + std::cout << "*********************\n"; \ + result = 1; \ + } + +int main() +{ + using namespace boost::python::converter::detail; + using namespace boost::python::converter; + using namespace boost::python; + using namespace boost; + + + ASSERT_SAME( + select_arg_to_python::type, value_arg_to_python + ); + + ASSERT_SAME( + select_arg_to_python >::type, reference_arg_to_python + ); + + ASSERT_SAME( + select_arg_to_python >::type, pointer_shallow_arg_to_python + ); + + ASSERT_SAME( + select_arg_to_python::type, pointer_deep_arg_to_python + ); + + ASSERT_SAME( + select_arg_to_python >::type, object_manager_arg_to_python > + ); + + ASSERT_SAME( + select_arg_to_python::type, object_manager_arg_to_python + ); + + ASSERT_SAME( + select_arg_to_python::type, arg_to_python + ); + + return result; +} diff --git a/test/select_holder.cpp b/test/select_holder.cpp new file mode 100644 index 00000000..febbeb2d --- /dev/null +++ b/test/select_holder.cpp @@ -0,0 +1,79 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include +#include + +#define BOOST_INCLUDE_MAIN +#include + +struct BR {}; + +struct Base {}; +struct Derived : Base {}; + +namespace boost { namespace python +{ + // specialization + template <> + struct has_back_reference
+ { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +}} // namespace boost::python + +template +void assert_same(U* = 0, T* = 0) +{ + BOOST_TEST((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + +} + +template +void assert_holder(T* = 0, Held* = 0, Holder* = 0) +{ + assert_same(boost::python::objects::select_holder::execute((Held*)0).get()); +} + +int test_main(int, char * []) +{ + using namespace boost::python::detail; + using namespace boost::python::objects; + + assert_holder >(); + + assert_holder >(); + assert_holder >(); + assert_holder >(); + + assert_holder >(); + + assert_holder + ,pointer_holder,Base> >(); + + assert_holder + ,pointer_holder_back_reference,Base> >(); + + assert_holder + ,pointer_holder_back_reference,BR> > (); + + return 0; +} + +#if !defined(_WIN32) || defined(__GNUC__) +// This definition is needed for MinGW 2.95.2 and KCC on OSF for some +// reason, but will break other Win32 compilers. +namespace boost { namespace python +{ + bool handle_exception_impl(boost::function0) { return false; } +}} +#endif diff --git a/test/str.cpp b/test/str.cpp new file mode 100644 index 00000000..646f8676 --- /dev/null +++ b/test/str.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +using namespace boost::python; + +object convert_to_string(object data) +{ + return str(data); +} + +void work_with_string(object print) +{ + str data("this is a demo string"); + print(data.split(" ")); + print(data.split(" ",3)); + print(str("<->").join(data.split(" "))); + print(data.capitalize()); + print('[' + data.center(30) + ']'); + print(data.count("t")); + print(data.encode("utf-8")); + print(data.decode("utf-8")); + print(data.endswith("xx")); + print(data.startswith("test")); + print(data.splitlines()); + print(data.strip()); + print(data.swapcase()); + print(data.title()); + + print("find"); + print(data.find("demo")); + print(data.find("demo"),3,5); + print(data.find(std::string("demo"))); + print(data.find(std::string("demo"),9)); + + print("expandtabs"); + str tabstr("\t\ttab\tdemo\t!"); + print(tabstr.expandtabs()); + print(tabstr.expandtabs(4)); + print(tabstr.expandtabs(7.9)); + + print("operators"); + print( str("part1") + str("part2") ); +// print( str("a test string").slice(3,_) ); +// print( str("another test")[5] ); + + print(data.replace("demo",std::string("blabla"))); + print(data.rfind("i",5)); + print(data.rindex("i",5)); + print(data.startswith("asdf")); + print(data.endswith("asdf")); + print(data.translate(str('a')*256)); + + + bool tmp = data.isalnum() || data.isalpha() || data.isdigit() || data.islower() || + data.isspace() || data.istitle() || data.isupper(); + (void)tmp; // ignored. +} + + +BOOST_PYTHON_MODULE_INIT(str_ext) +{ + def("convert_to_string",convert_to_string); + def("work_with_string",work_with_string); +} + diff --git a/test/str.py b/test/str.py new file mode 100644 index 00000000..666096b1 --- /dev/null +++ b/test/str.py @@ -0,0 +1,52 @@ +""" +>>> from str_ext import * +>>> def printer(*args): +... for x in args: print x, +... print +... +>>> work_with_string(printer) +['this', 'is', 'a', 'demo', 'string'] +['this', 'is', 'a', 'demo string'] +this<->is<->a<->demo<->string +This is a demo string +[ this is a demo string ] +2 +this is a demo string +this is a demo string +0 +0 +['this is a demo string'] +this is a demo string +THIS IS A DEMO STRING +This Is A Demo String +find +10 +10 3 5 +10 +10 +expandtabs + tab demo ! + tab demo ! + tab demo ! +operators +part1part2 +this is a blabla string +18 +18 +0 +0 +aaaaaaaaaaaaaaaaaaaaa +""" + +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 + sys.exit(run()[0]) diff --git a/test/string_literal.cpp b/test/string_literal.cpp new file mode 100644 index 00000000..882fbd4e --- /dev/null +++ b/test/string_literal.cpp @@ -0,0 +1,38 @@ +//#include +#include +#include +#include + +using namespace boost::python::detail; + + +template +void expect_string_literal(T const&) +{ + BOOST_STATIC_ASSERT(is_string_literal::value); +} + +int main() +{ + expect_string_literal("hello"); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(is_string_literal::value); + BOOST_STATIC_ASSERT(is_string_literal::value); + + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + BOOST_STATIC_ASSERT(!is_string_literal::value); + return 0; +} diff --git a/test/submod_subclass_api.cpp b/test/submod_subclass_api.cpp new file mode 100644 index 00000000..b2c5293e --- /dev/null +++ b/test/submod_subclass_api.cpp @@ -0,0 +1,231 @@ +// Copyright David Hawkes 2002. +// Permission is hereby granted to copy, use and modify this software +// for any purpose, including commercial distribution, provided this +// copyright notice is not removed. No warranty WHATSOEVER is provided with this +// software. Any user(s) accepts this software "as is" and as such they will not +// bind the author(s) to any claim of suitabilty for any purpose. + +// embed_test.cpp : substantial test of embedding python in c++ using boost + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost; +using namespace boost::python; + + +// The following macros are for our convenience and coding expediency... +// There is no particular recomendation that they be used elsewhere +// as they are not feature complete and are just sufficient to suport +// the code here + + +#define DEF(fn) def(#fn, fn) +#define DEF_C(c, fn) def(#fn, &c::fn) +#define DEF_C_CB(c, fn) def(#fn, &c##_callback::base_##fn) + +#define CLASS(c) class_ >(#c) +#define CLASS_CB(c) class_, noncopyable >(#c) + +#define START_CALLBACK_CLASS(c) \ +class c##_callback : public c \ +{ \ + typedef c __base__; \ +public: \ + c##_callback(PyObject* self) : m_self(self) {} \ +private: \ + PyObject* m_self; \ +public: + +#define END_CALLBACK_CLASS }; + + +#define CALLBACK_MEMBER0(fn, rtn) \ +rtn fn() { return call_method(m_self, #fn); } \ +rtn base_##fn() { return __base__::fn(); } + + +#define CALLBACK_MEMBER0C(fn, rtn) \ +rtn fn() const { return call_method(m_self, #fn); } \ +rtn base_##fn() const { return __base__::fn(); } +// End of convenience macros + +// useful support classes +template +struct class_object : public object +{ + typedef object base; + class_object() : m_class_ptr(NULL) {} + class_object(object const& o) : base(o) { init(); } + class_object& operator=(object const& o) + { + base::operator=(o); + init(); + return *this; + } + T* operator->() const { return m_class_ptr; } + T& operator*() const { return *m_class_ptr; } +private: + void init() + { + m_class_ptr = arg_from_python(ptr())(ptr()); + } + T* m_class_ptr; +}; + +template +struct item_object : public object +{ + typedef object base; + item_object() {} + item_object(object const& o) : base(o), m_class(arg_from_python(ptr())(ptr())) {} + item_object& operator=(object const& o) + { + base::operator=(o); + init(); + return *this; + } + operator T() { return m_class; } +private: + void init() + { + m_class = arg_from_python(ptr())(ptr()); + } + T m_class; +}; +// end of useful support classes + +// pass our args in this struct +struct main_args { + main_args(int _argc, char* _argv[]) : argc(_argc), argv(_argv) {} + int argc; + char** argv; +}; +int python_main(main_args const &ma); + +// python module init +BOOST_PYTHON_MODULE_INIT(python_main) +{ + DEF(python_main); + CLASS(main_args); +} + +// sub module tests +namespace sm { + +int test_func() { return 7; } + +BOOST_PYTHON_MODULE_INIT(sm_test) +{ + // define a submodule + boost::python::module(".sm"); + // define a 2nd submodule + boost::python::module(".sm.sm2"); + // define a test function to appear in 2nd submodule + DEF(test_func); +} + +// sub-module tests +int test() +{ + api::run_simple_string("import sm_test"); + if(api::call_statement("_0 = bpl_test('sub modules', sm_test.sm.sm2.test_func, _1)", test_func())) + return 1; + return 0; +} + +} + +// sub class tests +namespace sc { + +class c1 { +public: + c1() {} + class c2 { + public: + c2() : n(2) {} + int n; + }; + c2 t; +}; + +c1::c2 test_func() { + return c1().t; +} + +BOOST_PYTHON_MODULE_INIT(sc_test) +{ + class_("c1.c2") + .def_init() + .def_readwrite("n", &c1::c2::n); + CLASS(c1) + .def_init() + .def_readwrite("t", &c1::t); + DEF(test_func); +} + +// sub-class tests +int test() +{ + api::run_simple_string("import sc_test"); + if(api::call_statement("_0 = bpl_test('sub classes', lambda : sc_test.c1.c2().n, _1.n)", test_func())) + return 1; + if(api::call_statement("_0 = bpl_test('sub classes', lambda : sc_test.c1().t.n, _1.n)", test_func())) + return 1; + return 0; +} + +} + +// new main that will have a python execution frame +int main(int argc, char* argv[]) +{ + // default return value; + int rtn = 0; + // define all the built-in modules used + PyImport_AppendInittab("python_main", initpython_main); + PyImport_AppendInittab("sm_test", sm::initsm_test); + PyImport_AppendInittab("sc_test", sc::initsc_test); + // initialize python + Py_Initialize(); + // start a new block so that any objects are released prior to finalizing + { + // import our main module - this will also initialise boost + api::run_simple_string("import python_main"); + // We call back here so we have a proper python execution frame to work with + item_object o_rtn(api::call_statement("_0 = python_main.python_main(_1)", main_args(argc, argv))); + rtn = o_rtn; + } + // clean up + Py_Finalize(); + return rtn; +} + +char *bpl_test = +"def bpl_test(name, func, result):\n" +" print 'testing %s...' % name\n" +" if func() != result:\n" +" print 'failed'\n" +" return 1\n" +" else:\n" +" print 'OK'\n" +" return 0\n"; + + +int python_main(main_args const &ma) +{ + api::print("running...\n"); + api::call_statement(bpl_test); + if(sm::test()) + return 1; + if(sc::test()) + return 1; + return 0; +} diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp new file mode 100644 index 00000000..912f2dc5 --- /dev/null +++ b/test/test_builtin_converters.cpp @@ -0,0 +1,126 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include +#include +#include + +template +struct by_value +{ + static T rewrap(T x) + { + return x; + } +}; + +template +struct by_const_reference +{ + static T rewrap(T const& x) + { + return x; + } +}; + +template +struct by_reference +{ + static T rewrap(T& x) + { + return x; + } +}; + +using boost::python::def; +using boost::python::handle; +using boost::python::object; +using boost::python::borrowed; + +// Used to test that arbitrary handle<>s can be returned +handle get_type(handle<> x) +{ + return handle(borrowed(x->ob_type)); +} + +handle<> return_null_handle() +{ + return handle<>(); +} + +char const* rewrap_value_mutable_cstring(char* x) { return x; } + +BOOST_PYTHON_MODULE_INIT(builtin_converters) +{ + def("get_type", get_type); + def("return_null_handle", return_null_handle); + + def("rewrap_value_bool", by_value::rewrap); + def("rewrap_value_char", by_value::rewrap); + def("rewrap_value_signed_char", by_value::rewrap); + def("rewrap_value_unsigned_char", by_value::rewrap); + def("rewrap_value_int", by_value::rewrap); + def("rewrap_value_unsigned_int", by_value::rewrap); + def("rewrap_value_short", by_value::rewrap); + def("rewrap_value_unsigned_short", by_value::rewrap); + def("rewrap_value_long", by_value::rewrap); + def("rewrap_value_unsigned_long", by_value::rewrap); +// using Python's macro instead of Boost's - we don't seem to get the +// config right all the time. +#ifdef HAVE_LONG_LONG + def("rewrap_value_long_long", by_value::rewrap); + def("rewrap_value_unsigned_long_long", by_value::rewrap); +#endif + def("rewrap_value_float", by_value::rewrap); + def("rewrap_value_double", by_value::rewrap); + def("rewrap_value_long_double", by_value::rewrap); + def("rewrap_value_complex_float", by_value >::rewrap); + def("rewrap_value_complex_double", by_value >::rewrap); + def("rewrap_value_complex_long_double", by_value >::rewrap); + def("rewrap_value_string", by_value::rewrap); + def("rewrap_value_cstring", by_value::rewrap); + def("rewrap_value_handle", by_value >::rewrap); + def("rewrap_value_object", by_value::rewrap); + + // Expose this to illustrate our failings ;-). See test_builtin_converters.py + def("rewrap_value_mutable_cstring", rewrap_value_mutable_cstring); + + + def("rewrap_const_reference_bool", by_const_reference::rewrap); + def("rewrap_const_reference_char", by_const_reference::rewrap); + def("rewrap_const_reference_signed_char", by_const_reference::rewrap); + def("rewrap_const_reference_unsigned_char", by_const_reference::rewrap); + def("rewrap_const_reference_int", by_const_reference::rewrap); + def("rewrap_const_reference_unsigned_int", by_const_reference::rewrap); + def("rewrap_const_reference_short", by_const_reference::rewrap); + def("rewrap_const_reference_unsigned_short", by_const_reference::rewrap); + def("rewrap_const_reference_long", by_const_reference::rewrap); + def("rewrap_const_reference_unsigned_long", by_const_reference::rewrap); +// using Python's macro instead of Boost's - we don't seem to get the +// config right all the time. +#ifdef HAVE_LONG_LONG + def("rewrap_const_reference_long_long", by_const_reference::rewrap); + def("rewrap_const_reference_unsigned_long_long", by_const_reference::rewrap); +#endif + def("rewrap_const_reference_float", by_const_reference::rewrap); + def("rewrap_const_reference_double", by_const_reference::rewrap); + def("rewrap_const_reference_long_double", by_const_reference::rewrap); + def("rewrap_const_reference_complex_float", by_const_reference >::rewrap); + def("rewrap_const_reference_complex_double", by_const_reference >::rewrap); + def("rewrap_const_reference_complex_long_double", by_const_reference >::rewrap); + def("rewrap_const_reference_string", by_const_reference::rewrap); + def("rewrap_const_reference_cstring", by_const_reference::rewrap); + def("rewrap_const_reference_handle", by_const_reference >::rewrap); + def("rewrap_const_reference_object", by_const_reference::rewrap); + + + def("rewrap_reference_object", by_reference::rewrap); +} + diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py new file mode 100644 index 00000000..f6caf56b --- /dev/null +++ b/test/test_builtin_converters.py @@ -0,0 +1,236 @@ +""" +>>> from builtin_converters import * + +# Synthesize idendity functions in case long long not supported +>>> if not 'rewrap_value_long_long' in dir(): +... def rewrap_value_long_long(x): return long(x) +... def rewrap_value_unsigned_long_long(x): return long(x) +... def rewrap_const_reference_long_long(x): return long(x) +... def rewrap_const_reference_unsigned_long_long(x): return long(x) + +>>> rewrap_value_bool(None) +0 +>>> rewrap_value_bool(0) +0 +>>> rewrap_value_bool(33) +1 +>>> rewrap_value_char('x') +'x' + + Note that there's currently silent truncation of strings passed to + char arguments. + +>>> rewrap_value_char('xy') +'x' +>>> rewrap_value_signed_char(42) +42 +>>> rewrap_value_unsigned_char(42) +42 +>>> rewrap_value_int(42) +42 +>>> rewrap_value_unsigned_int(42) +42 +>>> rewrap_value_short(42) +42 +>>> rewrap_value_unsigned_short(42) +42 +>>> rewrap_value_long(42) +42 +>>> rewrap_value_unsigned_long(42) +42 +>>> rewrap_value_long_long(42) +42L +>>> rewrap_value_unsigned_long_long(42) +42L + + show that we have range checking. + +>>> try: rewrap_value_unsigned_short(-42) +... except OverflowError: pass +... else: print 'expected an OverflowError!' + +>>> try: rewrap_value_int(sys.maxint * 2) +... except OverflowError: pass +... else: print 'expected an OverflowError!' + + +>>> abs(rewrap_value_float(4.2) - 4.2) < .000001 +1 +>>> rewrap_value_double(4.2) - 4.2 +0.0 +>>> rewrap_value_long_double(4.2) - 4.2 +0.0 + +>>> abs(rewrap_value_complex_float(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_value_complex_double(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_value_complex_long_double(4+.2j) - (4+.2j)) < .000001 +1 + +>>> rewrap_value_cstring('hello, world') +'hello, world' +>>> rewrap_value_string('yo, wassup?') +'yo, wassup?' + +>>> rewrap_value_handle(1) +1 +>>> x = 'hi' +>>> assert rewrap_value_handle(x) is x +>>> assert rewrap_value_object(x) is x + + Note that we can currently get a mutable pointer into an immutable + Python string: + +>>> rewrap_value_mutable_cstring('hello, world') +'hello, world' + +>>> rewrap_const_reference_bool(None) +0 +>>> rewrap_const_reference_bool(0) +0 + +>>> try: rewrap_const_reference_bool('yes') +... except TypeError: pass +... else: print 'expected a TypeError exception' + +>>> rewrap_const_reference_char('x') +'x' + + Note that there's currently silent truncation of strings passed to + char arguments. + +>>> rewrap_const_reference_char('xy') +'x' +>>> rewrap_const_reference_signed_char(42) +42 +>>> rewrap_const_reference_unsigned_char(42) +42 +>>> rewrap_const_reference_int(42) +42 +>>> rewrap_const_reference_unsigned_int(42) +42 +>>> rewrap_const_reference_short(42) +42 +>>> rewrap_const_reference_unsigned_short(42) +42 +>>> rewrap_const_reference_long(42) +42 +>>> rewrap_const_reference_unsigned_long(42) +42 +>>> rewrap_const_reference_long_long(42) +42L +>>> rewrap_const_reference_unsigned_long_long(42) +42L + + +>>> abs(rewrap_const_reference_float(4.2) - 4.2) < .000001 +1 +>>> rewrap_const_reference_double(4.2) - 4.2 +0.0 +>>> rewrap_const_reference_long_double(4.2) - 4.2 +0.0 + +>>> abs(rewrap_const_reference_complex_float(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_const_reference_complex_double(4+.2j) - (4+.2j)) < .000001 +1 +>>> abs(rewrap_const_reference_complex_long_double(4+.2j) - (4+.2j)) < .000001 +1 + +>>> rewrap_const_reference_cstring('hello, world') +'hello, world' +>>> rewrap_const_reference_string('yo, wassup?') +'yo, wassup?' + +>>> rewrap_const_reference_handle(1) +1 +>>> x = 'hi' +>>> assert rewrap_const_reference_handle(x) is x +>>> assert rewrap_const_reference_object(x) is x +>>> assert rewrap_reference_object(x) is x + + +Check that None <==> NULL + +>>> rewrap_const_reference_cstring(None) + +But None cannot be converted to a string object: + +>>> try: rewrap_const_reference_string(None) +... except TypeError: pass +... else: print 'expected a TypeError exception' + +Now check implicit conversions between floating/integer types + +>>> rewrap_const_reference_float(42) +42.0 + +>>> rewrap_const_reference_float(42L) +42.0 + +>>> try: rewrap_const_reference_int(42.0) +... except TypeError: pass +... else: print 'expected a TypeError exception' + +>>> rewrap_value_float(42) +42.0 + +>>> try: rewrap_value_int(42.0) +... except TypeError: pass +... else: print 'expected a TypeError exception' + +Check that classic classes also work + +>>> class FortyTwo: +... def __int__(self): +... return 42 +... def __float__(self): +... return 42.0 +... def __complex__(self): +... return complex(4+.2j) +... def __str__(self): +... return '42' + +>>> try: rewrap_const_reference_float(FortyTwo()) +... except TypeError: pass +... else: print 'expected a TypeError exception' + +>>> try: rewrap_value_int(FortyTwo()) +... except TypeError: pass +... else: print 'expected a TypeError exception' + +>>> try: rewrap_const_reference_string(FortyTwo()) +... except TypeError: pass +... else: print 'expected a TypeError exception' + +>>> try: rewrap_value_complex_double(FortyTwo()) +... except TypeError: pass +... else: print 'expected a TypeError exception' + +# show that arbitrary handle instantiations can be returned +>>> get_type(1) is type(1) +1 + +>>> return_null_handle() is None +1 +""" + +def run(args = None): + import sys + import doctest + import builtin_converters + + if 'rewrap_value_long_long' in dir(builtin_converters): + print 'LONG_LONG supported, testing...' + else: + print 'LONG_LONG not supported, skipping those tests...' + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) diff --git a/test/test_cltree.py b/test/test_cltree.py new file mode 100644 index 00000000..8408f7f2 --- /dev/null +++ b/test/test_cltree.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +from cltree import basic,symbol,constant,variable + +b = basic() +c = constant() +s = symbol() +v = variable() + +assert isinstance(b,basic) +assert not isinstance(b,symbol) +assert not isinstance(b,constant) +assert not isinstance(b,variable) + +assert isinstance(c,basic) +assert isinstance(c,constant) +assert not isinstance(c,symbol) +assert not isinstance(c,variable) + +assert not isinstance(s,basic) +assert isinstance(s,symbol) +assert not isinstance(s,constant) +assert not isinstance(s,variable) + +assert isinstance(v,basic) +assert not isinstance(v,symbol) +assert not isinstance(v,constant) +assert isinstance(v,variable) + +print 'b=',b +assert repr(b)=='cltree.basic()' +print 's=',s +assert repr(s)!='cltree.wrapped_symbol()' # because not isinstance(s,basic) +print 'c=',c +assert repr(c)=='cltree.constant()' +print 'v=',v +assert repr(v)=='cltree.wrapped_variable()' + + +print 'ok' diff --git a/test/test_pointer_adoption.cpp b/test/test_pointer_adoption.cpp new file mode 100644 index 00000000..b04e3496 --- /dev/null +++ b/test/test_pointer_adoption.cpp @@ -0,0 +1,126 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include + +using namespace boost::python; + +int a_instances = 0; + +int num_a_instances() { return a_instances; } + +struct inner +{ + inner(std::string const& s) + : s(s) + {} + + void change(std::string const& new_s) + { + this->s = new_s; + } + + std::string s; +}; + +struct Base +{ + virtual ~Base() {} +}; + +struct A : Base +{ + A(std::string const& s) + : x(s) + { + ++a_instances; + } + + ~A() + { + --a_instances; + } + + std::string content() const + { + return x.s; + } + + inner& get_inner() + { + return x; + } + + inner x; +}; + +struct B +{ + B() : x(0) {} + B(A* x_) : x(x_) {} + + inner const* adopt(A* x) { this->x = x; return &x->get_inner(); } + + std::string a_content() + { + return x ? x->content() : std::string("empty"); + } + + A* x; +}; + + +A* create(std::string const& s) +{ + return new A(s); +} + +A* as_A(Base* b) +{ + return dynamic_cast(b); +} + +BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext) +{ + def("num_a_instances", num_a_instances); + + // Specify the manage_new_object return policy to take + // ownership of create's result + def("create", create, return_value_policy()); + + def("as_A", as_A, return_internal_reference<>()); + + class_("Base") + ; + + class_ >(no_init) + .def("content", &A::content) + .def("get_inner", &A::get_inner, return_internal_reference<>()) + ; + + class_(no_init) + .def("change", &inner::change) + ; + + class_("B") + .def_init(args(), with_custodian_and_ward_postcall<1,2>()) + + .def("adopt", &B::adopt + // Adopt returns a pointer referring to a subobject of its 2nd argument (1st being "self") + , return_internal_reference<2 + // Meanwhile, self holds a reference to the 2nd argument. + , with_custodian_and_ward<1,2> >() + ) + + .def("a_content", &B::a_content) + ; +} + +#include "module_tail.cpp" diff --git a/test/test_pointer_adoption.py b/test/test_pointer_adoption.py new file mode 100644 index 00000000..f684b062 --- /dev/null +++ b/test/test_pointer_adoption.py @@ -0,0 +1,90 @@ +""" +>>> from test_pointer_adoption_ext import * + +>>> num_a_instances() +0 + +>>> a = create('dynamically allocated') +>>> num_a_instances() +1 + +>>> a.content() +'dynamically allocated' + +>>> innards = a.get_inner() +>>> innards.change('with an exposed reference') +>>> a.content() +'with an exposed reference' + +# The a instance should be kept alive... +>>> a = None +>>> num_a_instances() +1 + +# ...until we're done with its innards +>>> innards = None +>>> num_a_instances() +0 + +>>> b = B() +>>> a = create('another') +>>> b.a_content() +'empty' +>>> innards = b.adopt(a); +>>> b.a_content() +'another' +>>> num_a_instances() +1 +>>> del a # innards and b are both holding a reference +>>> num_a_instances() +1 +>>> innards.change('yet another') +>>> b.a_content() +'yet another' + +>>> del innards +>>> num_a_instances() # b still owns a reference to a +1 +>>> del b +>>> num_a_instances() +0 + +Test call policies for constructors here + +>>> a = create('second a') +>>> num_a_instances() +1 +>>> b = B(a) +>>> num_a_instances() +1 +>>> a.content() +'second a' + +>>> del a +>>> num_a_instances() +1 +>>> b.a_content() +'second a' + +>>> del b +>>> num_a_instances() +0 + +>>> as_A(create('dynalloc')) is None +0 +>>> base = Base() +>>> as_A(base) is None +1 +""" +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 + sys.exit(run()[0]) diff --git a/test/tuple.cpp b/test/tuple.cpp new file mode 100644 index 00000000..d5569185 --- /dev/null +++ b/test/tuple.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +using namespace boost::python; + +object convert_to_tuple(object data) +{ + return tuple(data); +} + +void test_operators(tuple t1, tuple t2, object print) +{ + print(t1 + t2); +} + +tuple mktuple0() { return make_tuple(); } +tuple mktuple1(int x) { return make_tuple(x); } +tuple mktuple2(char const* a1, int x) { return make_tuple(a1, x); } + +BOOST_PYTHON_MODULE_INIT(tuple_ext) +{ + def("convert_to_tuple",convert_to_tuple); + def("test_operators",test_operators); + def("make_tuple", mktuple0); + def("make_tuple", mktuple1); + def("make_tuple", mktuple2); +} diff --git a/test/tuple.py b/test/tuple.py new file mode 100644 index 00000000..cd899df4 --- /dev/null +++ b/test/tuple.py @@ -0,0 +1,32 @@ +""" +>>> from tuple_ext import * +>>> def printer(*args): +... for x in args: print x, +... print +... +>>> print convert_to_tuple("this is a test string") +('t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', ' ', 's', 't', 'r', 'i', 'n', 'g') +>>> t1 = convert_to_tuple("this is") +>>> t2 = (1,2,3,4) +>>> test_operators(t1,t2,printer) +('t', 'h', 'i', 's', ' ', 'i', 's', 1, 2, 3, 4) +>>> make_tuple() +() +>>> make_tuple(42) +(42,) +>>> make_tuple('hello', 42) +('hello', 42) +""" + +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 + sys.exit(run()[0]) diff --git a/test/virtual_functions.cpp b/test/virtual_functions.cpp new file mode 100644 index 00000000..73d47dc5 --- /dev/null +++ b/test/virtual_functions.cpp @@ -0,0 +1,113 @@ +// Copyright David Abrahams 2002. 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 +#include +#include +#include +#include +#include + +using namespace boost::python; + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + virtual ~X() { assert(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int x) { assert(magic == 7654321); this->x = x; } + int value() const { assert(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +struct Y : X +{ + Y(int x) : X(x) {}; +}; + +struct abstract : X +{ + abstract(int x) : X(x) {}; + int call_f(Y const& y) { return f(y); } + virtual int f(Y const& y) = 0; +}; + +struct concrete : X +{ + concrete(int x) : X(x) {}; + int call_f(Y const& y) { return f(y); } + virtual int f(Y const& y) { set(y.value()); return y.value(); } +}; + +struct abstract_callback : abstract +{ + abstract_callback(PyObject* p, int x) + : abstract(x), self(p) + {} + + int f(Y const& y) + { + return call_method(self, "f", boost::ref(y)); + } + + PyObject* self; +}; + +struct concrete_callback : concrete +{ + concrete_callback(PyObject* p, int x) + : concrete(x), self(p) + {} + + concrete_callback(PyObject* p, concrete const& x) + : concrete(x), self(p) + {} + + int f(Y const& y) + { + return call_method(self, "f", boost::ref(y)); + } + + int f_impl(Y const& y) + { + return this->concrete::f(y); + } + + PyObject* self; +}; + +int X::counter; + +BOOST_PYTHON_MODULE_INIT(virtual_functions_ext) +{ + class_("concrete", args()) + .def("value", &concrete::value) + .def("set", &concrete::set) + .def("call_f", &concrete::call_f) + .def("f", &concrete_callback::f_impl) + ; + + class_ + >("abstract", args()) + + .def("value", &abstract::value) + .def("call_f", &abstract::call_f) + .def("set", &abstract::set) + ; + + class_("Y", args()) + .def("value", &Y::value) + .def("set", &Y::set) + ; +} + +#include "module_tail.cpp"