From e79a66851c02c061be6678d3a7118907d7305596 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Mar 2002 14:56:39 +0000 Subject: [PATCH] Beginning of callback implementation [SVN r13135] --- Jamfile | 104 +++--------------- .../python/converter/builtin_converters.hpp | 24 +++- .../converter/callback_to_python_base.hpp | 45 ++++++++ .../python/converter/find_from_python.hpp | 7 +- .../boost/python/converter/from_python.hpp | 42 +------ .../python/converter/from_python_data.hpp | 37 ++++++- .../converter/lvalue_from_python_chain.hpp | 67 +++++++++++ include/boost/python/converter/registry.hpp | 8 +- .../python/converter/to_python_function.hpp | 44 +++++--- .../converter/to_python_function_type.hpp | 30 +++++ include/boost/python/to_python_converter.hpp | 2 +- include/boost/python/to_python_value.hpp | 16 +-- src/converter/builtin_converters.cpp | 2 +- src/converter/from_python.cpp | 12 +- src/converter/registry.cpp | 8 +- src/object/function.cpp | 30 ++++- test/Jamfile | 75 +++++++++++++ test/test_builtin_converters.cpp | 4 +- test/test_builtin_converters.py | 2 +- 19 files changed, 381 insertions(+), 178 deletions(-) create mode 100644 include/boost/python/converter/callback_to_python_base.hpp create mode 100644 include/boost/python/converter/lvalue_from_python_chain.hpp create mode 100644 include/boost/python/converter/to_python_function_type.hpp create mode 100644 test/Jamfile diff --git a/Jamfile b/Jamfile index 9bf18e2e..4a1af66f 100644 --- a/Jamfile +++ b/Jamfile @@ -4,93 +4,21 @@ subproject libs/python ; SEARCH on python.jam = $(BOOST_BUILD_PATH) ; include python.jam ; - -{ - local BOOST_PYTHON_V2_PROPERTIES - = $(PYTHON_PROPERTIES) - <*>"-inline deferred" - <*>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers - BOOST_PYTHON_DYNAMIC_LIB - BOOST_PYTHON_V2 - ; - - local gcc-release-properties - = speed -fomit-frame-pointer - on -foptimize-sibling-calls - ; - - local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) $(gcc-release-properties) -; - - dll bpl - : - src/converter/from_python.cpp - src/converter/registry.cpp - src/converter/type_id.cpp - src/object/class.cpp - src/object/function.cpp - src/object/inheritance.cpp - src/object/life_support.cpp - src/errors.cpp - src/module.cpp - src/objects.cpp - src/converter/builtin_converters.cpp - : - $(BOOST_PYTHON_V2_PROPERTIES) - BOOST_PYTHON_SOURCE - ; - - # -------- general test ------- - extension m1 : test/m1.cpp bpl - : - : - ; - - extension m2 : test/m2.cpp bpl - : - : ; - - boost-python-runtest try : test/newtest.py m1 m2 : : ; - - # ----------- builtin converters ----------- - - extension builtin_converters_ext : test/test_builtin_converters.cpp bpl - : - : - ; - - boost-python-runtest test_builtin_converters : test/test_builtin_converters.py - builtin_converters_ext - : - : - ; - - # ----------- pointer adoption ----------- - - extension test_pointer_adoption_ext : test/test_pointer_adoption.cpp bpl - : - : - ; - - boost-python-runtest test_pointer_adoption : test/test_pointer_adoption.py - test_pointer_adoption_ext - : - : - ; - -} - -unit-test indirect_traits_test - : test/indirect_traits_test.cpp : $(BOOST_ROOT) ; -unit-test destroy_test - : test/destroy_test.cpp : $(BOOST_ROOT) ; -unit-test pointer_type_id_test - : test/pointer_type_id_test.cpp : $(BOOST_ROOT) ; - -unit-test select_from_python_test - : test/select_from_python_test.cpp +dll bpl + : + src/converter/from_python.cpp + src/converter/registry.cpp src/converter/type_id.cpp - src/converter/registry.cpp # MWerks needs this for some reason - : $(PYTHON_PROPERTIES) + src/object/class.cpp + src/object/function.cpp + src/object/inheritance.cpp + src/object/life_support.cpp + src/errors.cpp + src/module.cpp + src/objects.cpp + src/converter/builtin_converters.cpp + src/converter/callback.cpp + : + $(BOOST_PYTHON_V2_PROPERTIES) + BOOST_PYTHON_SOURCE ; - diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index 7ae7a357..4db0eb9c 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -7,6 +7,7 @@ # define BUILTIN_CONVERTERS_DWA2002124_HPP # include # include +# include # include # include @@ -23,6 +24,11 @@ namespace detail }; } +namespace converter +{ + template struct callback_to_python; +} + # define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ template <> struct to_python_value \ : detail::builtin_to_python \ @@ -39,7 +45,19 @@ namespace detail { \ return (expr); \ } \ - }; + }; \ + namespace converter \ + { \ + template <> struct callback_to_python< T > \ + { \ + callback_to_python(T const& x) \ + : m_held(expr) {} \ + PyObject* get() const \ + { return m_held.get(); } \ + private: \ + ref m_held; \ + }; \ + } # define BOOST_PYTHON_TO_INT(T) \ @@ -53,12 +71,12 @@ BOOST_PYTHON_TO_INT(int) BOOST_PYTHON_TO_INT(long) # undef BOOST_TO_PYTHON_INT -BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, x ? PyString_FromString(x) : detail::none()) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, x ? PyString_FromString(x) : boost::python::detail::none()) 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_TO_PYTHON_BY_VALUE(PyObject*, x ? x : detail::none()) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, (x ? x : boost::python::detail::none())) 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())) diff --git a/include/boost/python/converter/callback_to_python_base.hpp b/include/boost/python/converter/callback_to_python_base.hpp new file mode 100644 index 00000000..c878850e --- /dev/null +++ b/include/boost/python/converter/callback_to_python_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 CALLBACK_TO_PYTHON_BASE_DWA200237_HPP +# define CALLBACK_TO_PYTHON_BASE_DWA200237_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + struct callback_to_python_holder + { + callback_to_python_holder(PyObject* obj); + inline PyObject* get() const; + private: + ref m_held; + }; + + struct BOOST_PYTHON_DECL callback_to_python_base : callback_to_python_holder + { + callback_to_python_base(void const volatile* source, to_python_function_t); + }; + + // + // implmentation + // + inline callback_to_python_holder::callback_to_python_holder(PyObject* obj) + : m_held(obj) + { + } + + inline PyObject* callback_to_python_holder::get() const + { + return m_held.get(); + } +} + +}}} // namespace boost::python::converter + +#endif // CALLBACK_TO_PYTHON_BASE_DWA200237_HPP diff --git a/include/boost/python/converter/find_from_python.hpp b/include/boost/python/converter/find_from_python.hpp index 863c44a6..e7f7ca81 100644 --- a/include/boost/python/converter/find_from_python.hpp +++ b/include/boost/python/converter/find_from_python.hpp @@ -8,17 +8,18 @@ # include # include +# include namespace boost { namespace python { namespace converter { struct lvalue_from_python_registration; struct rvalue_from_python_registration; -struct rvalue_stage1_data; BOOST_PYTHON_DECL void* find( PyObject* source, lvalue_from_python_registration const*); -BOOST_PYTHON_DECL void* find( - PyObject* source, rvalue_from_python_registration const*, rvalue_stage1_data&); + +BOOST_PYTHON_DECL rvalue_stage1_data find( + PyObject* source, rvalue_from_python_registration const*); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp index f9192be2..5fe8901a 100644 --- a/include/boost/python/converter/from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -8,13 +8,14 @@ # include # include -# include # include # include # include # include # include # include +# include +# include namespace boost { namespace python { namespace converter { @@ -42,8 +43,6 @@ struct pointer_const_reference_from_python private: typename detail::referent_storage::type m_result; - - static lvalue_from_python_registration*& chain; }; // Used when T == U* @@ -52,8 +51,6 @@ struct pointer_from_python : from_python_base { pointer_from_python(PyObject*); T operator()(PyObject*) const; - - static lvalue_from_python_registration*& chain; }; // Used when T == U& and (T != V const& or T == W volatile&) @@ -62,8 +59,6 @@ struct reference_from_python : from_python_base { reference_from_python(PyObject*); T operator()(PyObject*) const; - - static lvalue_from_python_registration*& chain; }; // ------- rvalue converters --------- @@ -79,14 +74,12 @@ class rvalue_from_python public: rvalue_from_python(PyObject*); - ~rvalue_from_python(); bool convertible() const; result_type operator()(PyObject*); private: rvalue_data m_data; - static rvalue_from_python_registration*& chain; }; template @@ -191,7 +184,7 @@ inline pointer_const_reference_from_python::pointer_const_reference_from_pyth { detail::write_void_ptr_reference( m_result.bytes - , p == Py_None ? p : find(p, chain) + , p == Py_None ? p : find(p, lvalue_from_python_chain::value) , (T(*)())0); } @@ -208,15 +201,11 @@ inline T pointer_const_reference_from_python::operator()(PyObject* p) const : detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); } -template -lvalue_from_python_registration*& pointer_const_reference_from_python::chain - = registry::lvalue_converters(pointer_type_id()); - // -------- template inline pointer_from_python::pointer_from_python(PyObject* p) - : from_python_base(p == Py_None ? p : find(p, chain)) + : from_python_base(p == Py_None ? p : find(p, lvalue_from_python_chain::value)) { } @@ -226,15 +215,11 @@ inline T pointer_from_python::operator()(PyObject* p) const return (p == Py_None) ? 0 : T(result()); } -template -lvalue_from_python_registration*& pointer_from_python::chain - = registry::lvalue_converters(pointer_type_id()); - // -------- template inline reference_from_python::reference_from_python(PyObject* p) - : from_python_base(find(p,chain)) + : from_python_base(find(p,lvalue_from_python_chain::value)) { } @@ -244,23 +229,12 @@ inline T reference_from_python::operator()(PyObject*) const return detail::void_ptr_to_reference(result(), (T(*)())0); } -template -lvalue_from_python_registration*& reference_from_python::chain - = registry::lvalue_converters(undecorated_type_id()); - // ------- template inline rvalue_from_python::rvalue_from_python(PyObject* obj) + : m_data(find(obj, rvalue_from_python_chain::value)) { - find(obj, chain, m_data.stage1); -} - -template -inline rvalue_from_python::~rvalue_from_python() -{ - if (m_data.stage1.convertible == m_data.storage.bytes) - python::detail::destroy_reference(m_data.storage.bytes); } template @@ -279,10 +253,6 @@ rvalue_from_python::operator()(PyObject* p) return detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); } -template -rvalue_from_python_registration*& rvalue_from_python::chain - = registry::rvalue_converters(undecorated_type_id()); - }}} // namespace boost::python::converter #endif // FROM_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp index 9b418957..9fa9410a 100644 --- a/include/boost/python/converter/from_python_data.hpp +++ b/include/boost/python/converter/from_python_data.hpp @@ -16,6 +16,7 @@ # include # include # include +# include # include # include # include @@ -161,7 +162,7 @@ namespace detail } template -struct rvalue_data +struct rvalue_base_data { rvalue_stage1_data stage1; @@ -170,6 +171,40 @@ struct rvalue_data >::type storage; }; +template +struct rvalue_data : rvalue_base_data +{ + rvalue_data(rvalue_stage1_data const&); + rvalue_data(void*); + ~rvalue_data(); +}; + +// +// Implementataions +// +template +inline rvalue_data::rvalue_data(rvalue_stage1_data const& stage1) +{ + this->stage1 = stage1; +} + +template +inline rvalue_data::rvalue_data(void* convertible) +{ + this->stage1.convertible = convertible; +} + +template +inline rvalue_data::~rvalue_data() +{ + if (this->stage1.convertible == this->storage.bytes) + python::detail::destroy_reference< + add_reference< + add_cv::type + >::type + >(storage.bytes); +} + }}} // namespace boost::python::converter #endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/include/boost/python/converter/lvalue_from_python_chain.hpp b/include/boost/python/converter/lvalue_from_python_chain.hpp new file mode 100644 index 00000000..f1417460 --- /dev/null +++ b/include/boost/python/converter/lvalue_from_python_chain.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 LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +# define LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// Given T == U*cv&, T == U*, or T == U&, lvalue_from_python_chain +// declares a "templated global reference" to the lvalue from_python +// converter chain for U +namespace detail +{ + template + struct ptr_or_ptr_ref_lvalue_from_python_chain + { + static lvalue_from_python_registration*const& value; + }; + + template + lvalue_from_python_registration*const& + ptr_or_ptr_ref_lvalue_from_python_chain::value + = registry::lvalue_converters(pointer_type_id()); + + template + struct ref_lvalue_from_python_chain + { + static lvalue_from_python_registration*const& value; + }; + + template + lvalue_from_python_registration*const& + ref_lvalue_from_python_chain::value + = registry::lvalue_converters(undecorated_type_id()); + + template + struct select_lvalue_from_python_chain + { + BOOST_STATIC_CONSTANT( + bool, ptr = boost::python::detail::is_reference_to_pointer::value + || is_pointer::value); + + typedef typename add_reference::type>::type normalized; + + typedef typename mpl::select_type< + ptr + , ptr_or_ptr_ref_lvalue_from_python_chain + , ref_lvalue_from_python_chain + >::type type; + }; +} + +template +struct lvalue_from_python_chain + : detail::select_lvalue_from_python_chain::type +{ +}; + +}}} // namespace boost::python::converter + +#endif // LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index a511a1a4..1c8dba24 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -8,7 +8,7 @@ # include # include # include -# include +# include # include namespace boost { namespace python { namespace converter { @@ -22,10 +22,10 @@ namespace registry BOOST_PYTHON_DECL lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t); BOOST_PYTHON_DECL rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t); - BOOST_PYTHON_DECL to_python_value_function const& - to_python_function(undecorated_type_id_t); + BOOST_PYTHON_DECL to_python_function_t const& + get_to_python_function(undecorated_type_id_t); - BOOST_PYTHON_DECL void insert(to_python_value_function, undecorated_type_id_t); + BOOST_PYTHON_DECL void insert(to_python_function_t, undecorated_type_id_t); // Insert an lvalue from_python converter BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), undecorated_type_id_t); diff --git a/include/boost/python/converter/to_python_function.hpp b/include/boost/python/converter/to_python_function.hpp index a438ce0c..ff3891e2 100644 --- a/include/boost/python/converter/to_python_function.hpp +++ b/include/boost/python/converter/to_python_function.hpp @@ -8,23 +8,41 @@ # include # include +# include +# include +# include +# include namespace boost { namespace python { namespace converter { -// The type of stored function pointers which actually do conversion -// by-value. The void* points to the object to be converted, and -// type-safety is preserved through runtime registration. -typedef PyObject* (*to_python_value_function)(void const*); - -// Given a typesafe to_python conversion function, produces a -// to_python_value_function which can be registered in the usual way. -template -struct as_to_python_value_function +// to_python_function -- +// +// essentially a "templated global reference" which holds the +// converter for converting a type to Python by-value. We "normalize" +// T by adding "const volatile&" so that fewer global variables and +// associated static initializations are generated. +namespace detail +{ + template + struct to_python_function_base + { + static to_python_function_t const& value; + }; + + template + to_python_function_t const& + to_python_function_base::value + = converter::registry::get_to_python_function(undecorated_type_id()); +} + +template +struct to_python_function + : detail::to_python_function_base< + typename add_reference< + typename add_cv::type + >::type + > { - static PyObject* convert(void const* x) - { - return ToPython::convert(*(T const*)x); - } }; }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/to_python_function_type.hpp b/include/boost/python/converter/to_python_function_type.hpp new file mode 100644 index 00000000..197654e5 --- /dev/null +++ b/include/boost/python/converter/to_python_function_type.hpp @@ -0,0 +1,30 @@ +// 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_FUNCTION_TYPE_DWA200236_HPP +# define TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP +# include + +namespace boost { namespace python { namespace converter { + +// The type of stored function pointers which actually do conversion +// by-value. The void* points to the object to be converted, and +// type-safety is preserved through runtime registration. +typedef PyObject* (*to_python_function_t)(void const*); + +// Given a typesafe to_python conversion function, produces a +// to_python_function_t which can be registered in the usual way. +template +struct as_to_python_function +{ + static PyObject* convert(void const* x) + { + return ToPython::convert(*(T const*)x); + } +}; + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP diff --git a/include/boost/python/to_python_converter.hpp b/include/boost/python/to_python_converter.hpp index 7e46c505..47473419 100644 --- a/include/boost/python/to_python_converter.hpp +++ b/include/boost/python/to_python_converter.hpp @@ -25,7 +25,7 @@ struct to_python_converter template to_python_converter::to_python_converter() { - typedef converter::as_to_python_value_function< + typedef converter::as_to_python_function< T, Conversion > normalized; diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index ecff5808..ffb68ada 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -23,25 +23,14 @@ struct to_python_value static bool convertible(); PyObject* operator()(argument_type) const; - - private: - // Note that this is a pointer to a function pointer - static converter::to_python_value_function const* fconvert; }; -template -converter::to_python_value_function const* -to_python_value::fconvert - = &converter::registry::to_python_function(converter::undecorated_type_id()); - - template bool to_python_value::convertible() { // if this assert fires, our static variable hasn't been set up yet. - assert(fconvert != 0); - return *fconvert != 0; + return converter::to_python_function::value != 0; } template @@ -49,8 +38,7 @@ PyObject* to_python_value::operator()(argument_type x) const { // This might be further optimized on platforms which dynamically // link without specific imports/exports - converter::to_python_value_function f = *fconvert; - return f(&x); + return converter::to_python_function::value(&x); } }} // namespace boost::python diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index fe6708e6..87d0d7b4 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -56,7 +56,7 @@ namespace ref intermediate(creator(obj)); // Get the location in which to construct - void* storage = ((rvalue_data*)data)->storage.bytes; + void* storage = ((rvalue_base_data*)data)->storage.bytes; new (storage) T(SlotPolicy::extract(intermediate.get())); // record successful construction diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 57aee355..8a68cc44 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -10,21 +10,23 @@ namespace boost { namespace python { namespace converter { -BOOST_PYTHON_DECL void* find( +BOOST_PYTHON_DECL rvalue_stage1_data find( PyObject* source - , rvalue_from_python_registration const* chain - , rvalue_stage1_data& data) + , rvalue_from_python_registration const* chain) { + rvalue_stage1_data data; + data.convertible = 0; for (;chain != 0; chain = chain->next) { void* r = chain->convertible(source); if (r != 0) { + data.convertible = r; data.construct = chain->construct; - return data.convertible = r; + break; } } - return data.convertible = 0; + return data; } BOOST_PYTHON_DECL void* find( diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index bdfa1c8a..2d104b01 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -19,7 +19,7 @@ namespace // entry(); // The unique to_python converter for the associated C++ type. - to_python_value_function m_to_python_converter; + to_python_function_t m_to_python_converter; // The collection of from_python converters for the associated // C++ type. @@ -66,15 +66,15 @@ namespace // namespace registry { - to_python_value_function const& to_python_function( + to_python_function_t const& get_to_python_function( undecorated_type_id_t key) { return find(key)->m_to_python_converter; } - void insert(to_python_value_function f, undecorated_type_id_t source_t) + void insert(to_python_function_t f, undecorated_type_id_t source_t) { - to_python_value_function& slot = find(source_t)->m_to_python_converter; + to_python_function_t& slot = find(source_t)->m_to_python_converter; assert(slot == 0); // we have a problem otherwise if (slot != 0) { diff --git a/src/object/function.cpp b/src/object/function.cpp index a30e9f15..a9f0c94d 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -112,6 +112,30 @@ void function::add_to_namespace( throw error_already_set(); } +namespace +{ + struct bind_return + { + bind_return(PyObject*& result, function const* f, PyObject* args, PyObject* keywords) + : m_result(result) + , m_f(f) + , m_args(args) + , m_keywords(keywords) + {} + + void operator()() const + { + m_result = m_f->call(m_args, m_keywords); + } + + private: + PyObject*& m_result; + function const* m_f; + PyObject* m_args; + PyObject* m_keywords; + }; +} + extern "C" { // Stolen from Python's funcobject.c @@ -130,9 +154,11 @@ extern "C" } static PyObject * - function_call(PyObject *func, PyObject *arg, PyObject *kw) + function_call(PyObject *func, PyObject *args, PyObject *kw) { - return static_cast(func)->call(arg, kw); + PyObject* result = 0; + handle_exception(bind_return(result, static_cast(func), args, kw)); + return result; } } diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 00000000..767b07e6 --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,75 @@ +subproject libs/python/test ; + +# bring in the rules for python +SEARCH on python.jam = $(BOOST_BUILD_PATH) ; +include python.jam ; + +local PYTHON_V1_PROPERTIES = $(PYTHON_PROPERTIES) ; +local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) ; + +# +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 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 callbacks ; + +# --- unit tests of library components --- +unit-test indirect_traits_test + : indirect_traits_test.cpp : $(BOOST_ROOT) ; +unit-test destroy_test + : destroy_test.cpp : $(BOOST_ROOT) ; +unit-test pointer_type_id_test + : pointer_type_id_test.cpp : $(BOOST_ROOT) ; + +unit-test select_from_python_test + : select_from_python_test.cpp + ../src/converter/type_id.cpp + # ../src/converter/registry.cpp # MWerks needs this for some reason + + : $(BOOST_ROOT) BOOST_PYTHON_STATIC_LIB + $(PYTHON_V1_PROPERTIES) + ; + diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp index 4c07d9f4..939f9dc4 100644 --- a/test/test_builtin_converters.cpp +++ b/test/test_builtin_converters.cpp @@ -25,9 +25,9 @@ struct by_const_reference } }; -BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) +BOOST_PYTHON_MODULE_INIT(builtin_converters) { - boost::python::module("builtin_converters_ext") + boost::python::module("builtin_converters") .def("rewrap_value_bool", by_value::rewrap) .def("rewrap_value_signed_char", by_value::rewrap) diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py index 50d436e5..3958c15a 100644 --- a/test/test_builtin_converters.py +++ b/test/test_builtin_converters.py @@ -1,5 +1,5 @@ """ ->>> from builtin_converters_ext import * +>>> from builtin_converters import * >>> rewrap_value_bool(None) 0 >>> rewrap_value_bool(0)