From 97e4b34a15978ca9d7c296da2de89b78bba4e0d5 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 22 Sep 2016 19:46:38 -0400 Subject: [PATCH] Add support for std::shared_ptr. --- include/boost/python/converter/registered.hpp | 37 ++-- .../converter/shared_ptr_from_python.hpp | 78 +++---- .../python/converter/shared_ptr_to_python.hpp | 29 ++- include/boost/python/detail/is_shared_ptr.hpp | 18 +- .../python/detail/value_is_shared_ptr.hpp | 23 +- .../boost/python/object/class_metadata.hpp | 95 ++++---- include/boost/python/to_python_value.hpp | 52 +++-- test/SConscript | 3 +- test/boost_shared_ptr.cpp | 20 ++ test/boost_shared_ptr.py | 130 +++++++++++ test/shared_ptr.cpp | 206 +----------------- test/shared_ptr.hpp | 206 ++++++++++++++++++ test/shared_ptr.py | 4 +- 13 files changed, 559 insertions(+), 342 deletions(-) create mode 100644 test/boost_shared_ptr.cpp create mode 100644 test/boost_shared_ptr.py create mode 100644 test/shared_ptr.hpp diff --git a/include/boost/python/converter/registered.hpp b/include/boost/python/converter/registered.hpp index ad9a00b3..a622250d 100644 --- a/include/boost/python/converter/registered.hpp +++ b/include/boost/python/converter/registered.hpp @@ -1,19 +1,21 @@ // Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef REGISTERED_DWA2002710_HPP -# define REGISTERED_DWA2002710_HPP -# include -# include -# include -# include -# include -# include -# include -# include -# include +#ifndef boost_python_converter_registered_hpp_ +#define boost_python_converter_registered_hpp_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include #if defined(BOOST_PYTHON_TRACE_REGISTRY) \ || defined(BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND) # include @@ -75,7 +77,16 @@ namespace detail { registry::lookup_shared_ptr(type_id >()); } - + +#if __cplusplus >= 201103L + template + inline void + register_shared_ptr0(std::shared_ptr*) + { + registry::lookup_shared_ptr(type_id >()); + } +#endif + template inline void register_shared_ptr1(T const volatile*) @@ -112,4 +123,4 @@ namespace detail }}} // namespace boost::python::converter -#endif // REGISTERED_DWA2002710_HPP +#endif diff --git a/include/boost/python/converter/shared_ptr_from_python.hpp b/include/boost/python/converter/shared_ptr_from_python.hpp index c0910776..bb2ae863 100644 --- a/include/boost/python/converter/shared_ptr_from_python.hpp +++ b/include/boost/python/converter/shared_ptr_from_python.hpp @@ -1,63 +1,65 @@ // Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef SHARED_PTR_FROM_PYTHON_DWA20021130_HPP -# define SHARED_PTR_FROM_PYTHON_DWA20021130_HPP -# include -# include -# include -# include -# include +#ifndef boost_python_converter_shared_ptr_from_python_hpp_ +#define boost_python_converter_shared_ptr_from_python_hpp_ + +#include +#include +#include +#include +#include #ifndef BOOST_PYTHON_NO_PY_SIGNATURES # include #endif -# include +#include +#include namespace boost { namespace python { namespace converter { -template +template class SP> struct shared_ptr_from_python { - shared_ptr_from_python() - { - converter::registry::insert(&convertible, &construct, type_id >() + shared_ptr_from_python() + { + converter::registry::insert(&convertible, &construct, type_id >() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES - , &converter::expected_from_python_type_direct::get_pytype + , &converter::expected_from_python_type_direct::get_pytype #endif - ); - } + ); + } private: - static void* convertible(PyObject* p) - { - if (p == Py_None) - return p; + static void* convertible(PyObject* p) + { + if (p == Py_None) + return p; - return converter::get_lvalue_from_python(p, registered::converters); - } + return converter::get_lvalue_from_python(p, registered::converters); + } - static void construct(PyObject* source, rvalue_from_python_stage1_data* data) + static void construct(PyObject* source, rvalue_from_python_stage1_data* data) + { + void* const storage = ((converter::rvalue_from_python_storage >*)data)->storage.bytes; + // Deal with the "None" case. + if (data->convertible == source) + new (storage) SP(); + else { - void* const storage = ((converter::rvalue_from_python_storage >*)data)->storage.bytes; - // Deal with the "None" case. - if (data->convertible == source) - new (storage) shared_ptr(); - else - { - boost::shared_ptr hold_convertible_ref_count( - (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); - // use aliasing constructor - new (storage) shared_ptr( - hold_convertible_ref_count, - static_cast(data->convertible)); - } - - data->convertible = storage; + SP hold_convertible_ref_count( + (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); + // use aliasing constructor + new (storage) SP(hold_convertible_ref_count, + static_cast(data->convertible)); } + + data->convertible = storage; + } }; }}} // namespace boost::python::converter -#endif // SHARED_PTR_FROM_PYTHON_DWA20021130_HPP +#endif diff --git a/include/boost/python/converter/shared_ptr_to_python.hpp b/include/boost/python/converter/shared_ptr_to_python.hpp index fe867ace..cc686461 100644 --- a/include/boost/python/converter/shared_ptr_to_python.hpp +++ b/include/boost/python/converter/shared_ptr_to_python.hpp @@ -1,14 +1,16 @@ // Copyright David Abrahams 2003. +// Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef SHARED_PTR_TO_PYTHON_DWA2003224_HPP -# define SHARED_PTR_TO_PYTHON_DWA2003224_HPP -# include -# include -# include -# include +#ifndef boost_python_converter_shared_ptr_to_python_hpp_ +#define boost_python_converter_shared_ptr_to_python_hpp_ + +#include +#include +#include +#include namespace boost { namespace python { namespace converter { @@ -23,6 +25,19 @@ PyObject* shared_ptr_to_python(shared_ptr const& x) return converter::registered const&>::converters.to_python(&x); } +#if __cplusplus >= 201103L +template +PyObject* shared_ptr_to_python(std::shared_ptr const& x) +{ + if (!x) + return python::detail::none(); + else if (shared_ptr_deleter* d = std::get_deleter(x)) + return incref(get_pointer(d->owner)); + else + return converter::registered const&>::converters.to_python(&x); +} +#endif + }}} // namespace boost::python::converter -#endif // SHARED_PTR_TO_PYTHON_DWA2003224_HPP +#endif diff --git a/include/boost/python/detail/is_shared_ptr.hpp b/include/boost/python/detail/is_shared_ptr.hpp index 547af3f1..bef0e05a 100755 --- a/include/boost/python/detail/is_shared_ptr.hpp +++ b/include/boost/python/detail/is_shared_ptr.hpp @@ -1,17 +1,23 @@ // Copyright David Abrahams 2003. +// Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef IS_SHARED_PTR_DWA2003224_HPP -# define IS_SHARED_PTR_DWA2003224_HPP -# include -# include +#ifndef boost_python_detail_is_shared_ptr_hpp_ +#define boost_python_detail_is_shared_ptr_hpp_ + +#include +#include namespace boost { namespace python { namespace detail { BOOST_PYTHON_IS_XXX_DEF(shared_ptr, shared_ptr, 1) - +#if __cplusplus >= 201103L +template +struct is_shared_ptr > : std::true_type {}; +#endif + }}} // namespace boost::python::detail -#endif // IS_SHARED_PTR_DWA2003224_HPP +#endif diff --git a/include/boost/python/detail/value_is_shared_ptr.hpp b/include/boost/python/detail/value_is_shared_ptr.hpp index 361c369b..53e687f0 100644 --- a/include/boost/python/detail/value_is_shared_ptr.hpp +++ b/include/boost/python/detail/value_is_shared_ptr.hpp @@ -1,17 +1,28 @@ // Copyright David Abrahams 2003. +// Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef VALUE_IS_SHARED_PTR_DWA2003224_HPP -# define VALUE_IS_SHARED_PTR_DWA2003224_HPP -# include -# include +#ifndef boost_python_detail_value_is_shared_ptr_hpp_ +#define boost_python_detail_value_is_shared_ptr_hpp_ + +#include +#include namespace boost { namespace python { namespace detail { -BOOST_PYTHON_VALUE_IS_XXX_DEF(shared_ptr, shared_ptr, 1) - +template +struct value_is_shared_ptr +{ + static bool const value = is_shared_ptr + ::type> + ::type> + ::value; + typedef mpl::bool_ type; +}; + }}} // namespace boost::python::detail #endif // VALUE_IS_SHARED_PTR_DWA2003224_HPP diff --git a/include/boost/python/object/class_metadata.hpp b/include/boost/python/object/class_metadata.hpp index 5009c176..8e750b85 100644 --- a/include/boost/python/object/class_metadata.hpp +++ b/include/boost/python/object/class_metadata.hpp @@ -1,43 +1,46 @@ -// Copyright David Abrahams 2004. Distributed under the Boost -// Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef CLASS_METADATA_DWA2004719_HPP -# define CLASS_METADATA_DWA2004719_HPP -# include +// Copyright David Abrahams 2004. +// Copyright Stefan Seefeld 2016. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) -# include -# include -# include -# include -# include -# include +#ifndef boost_python_object_class_metadata_hpp_ +#define boost_python_object_class_metadata_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 +#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 objects { @@ -80,18 +83,22 @@ struct register_base_of // Preamble of register_class. Also used for callback classes, which // need some registration of their own. // + template inline void register_shared_ptr_from_python_and_casts(T*, Bases) { - // Constructor performs registration - python::detail::force_instantiate(converter::shared_ptr_from_python()); + // Constructor performs registration + python::detail::force_instantiate(converter::shared_ptr_from_python()); +#if __cplusplus >= 201103L + python::detail::force_instantiate(converter::shared_ptr_from_python()); +#endif - // - // register all up/downcasts here. We're using the alternate - // interface to mpl::for_each to avoid an MSVC 6 bug. - // - register_dynamic_id(); - mpl::for_each(register_base_of(), (Bases*)0, (add_pointer*)0); + // + // register all up/downcasts here. We're using the alternate + // interface to mpl::for_each to avoid an MSVC 6 bug. + // + register_dynamic_id(); + mpl::for_each(register_base_of(), (Bases*)0, (add_pointer*)0); } // @@ -220,8 +227,7 @@ struct class_metadata template inline static void register_aux2(T2*, Callback) { - objects::register_shared_ptr_from_python_and_casts((T2*)0, bases()); - + objects::register_shared_ptr_from_python_and_casts((T2*)0, bases()); class_metadata::maybe_register_callback_class((T2*)0, Callback()); class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable()); @@ -282,9 +288,8 @@ struct class_metadata template inline static void maybe_register_callback_class(T2*, mpl::true_) { - objects::register_shared_ptr_from_python_and_casts( + objects::register_shared_ptr_from_python_and_casts( (wrapped*)0, mpl::single_view()); - // explicit qualification of type_id makes msvc6 happy objects::copy_class_object(python::type_id(), python::type_id()); } @@ -292,4 +297,4 @@ struct class_metadata }}} // namespace boost::python::object -#endif // CLASS_METADATA_DWA2004719_HPP +#endif diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index aaabb9cf..2681f8a3 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -1,30 +1,32 @@ // Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef TO_PYTHON_VALUE_DWA200221_HPP -# define TO_PYTHON_VALUE_DWA200221_HPP -# include +#ifndef boost_python_to_python_value_hpp_ +#define boost_python_to_python_value_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 +#include +#include namespace boost { namespace python { @@ -114,10 +116,16 @@ struct object_manager_get_pytype BOOST_STATIC_CONSTANT(bool, uses_registry = false); private: #ifndef BOOST_PYTHON_NO_PY_SIGNATURES - template - PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} - template - PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} + template + PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} + template + PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} +# if __cplusplus >= 201103L + template + PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} + template + PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} +# endif #endif }; } @@ -168,4 +176,4 @@ namespace detail }} // namespace boost::python -#endif // TO_PYTHON_VALUE_DWA200221_HPP +#endif diff --git a/test/SConscript b/test/SConscript index c62b8bc4..c1ab335d 100644 --- a/test/SConscript +++ b/test/SConscript @@ -38,7 +38,7 @@ for test in [('injected',), ('properties',), ('return_arg',), ('staticmethod',), - ('shared_ptr',), + ('boost_shared_ptr',), ('enable_shared_from_this',), ('andreas_beyer',), ('polymorphism',), @@ -94,6 +94,7 @@ for test in [('injected',), if env['CXX11']: for test in [ + ('shared_ptr',), ]: tests+=env.BPLTest(*test) else: diff --git a/test/boost_shared_ptr.cpp b/test/boost_shared_ptr.cpp new file mode 100644 index 00000000..57e50aa3 --- /dev/null +++ b/test/boost_shared_ptr.cpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include + +using boost::shared_ptr; +#define MODULE boost_shared_ptr_ext + +#include "shared_ptr.hpp" +#include "module_tail.cpp" + diff --git a/test/boost_shared_ptr.py b/test/boost_shared_ptr.py new file mode 100644 index 00000000..31a2ad3d --- /dev/null +++ b/test/boost_shared_ptr.py @@ -0,0 +1,130 @@ +# Copyright David Abrahams 2004. Distributed under the Boost +# Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +''' +>>> from boost_shared_ptr_ext import * + + Test that shared_ptr can be converted to shared_ptr + +>>> Y.store(YYY(42)) + +>>> x = X(17) +>>> null_x = null(x) +>>> null_x # should be None +>>> identity(null_x) # should also be None + +>>> a = New(1) +>>> A.call_f(a) +1 +>>> New(0) + +>>> type(factory(3)) + +>>> type(factory(42)) + + +>>> class P(Z): +... def v(self): +... return -Z.v(self); +... def __del__(self): +... print('bye') +... +>>> p = P(12) +>>> p.value() +12 +>>> p.v() +-12 +>>> look(p) +12 +>>> try: modify(p) +... except TypeError: pass +... else: 'print(expected a TypeError)' +>>> look(None) +-1 +>>> store(p) +>>> del p +>>> Z.get().v() +-12 +>>> Z.count() +1 +>>> Z.look_store() +12 +>>> Z.release() +bye +>>> Z.count() +0 + +>>> z = Z(13) +>>> z.value() +13 +>>> z.v() +13 +>>> try: modify(z) +... except TypeError: pass +... else: 'print(expected a TypeError)' + +>>> Z.get() # should be None +>>> store(z) +>>> assert Z.get() is z # show that deleter introspection works +>>> del z +>>> Z.get().value() +13 +>>> Z.count() +1 +>>> Z.look_store() +13 +>>> Z.release() +>>> Z.count() +0 + +>>> x = X(17) +>>> x.value() +17 +>>> look(x) +17 +>>> try: modify(x) +... except TypeError: pass +... else: 'print(expected a TypeError)' +>>> look(None) +-1 +>>> store(x) +>>> del x +>>> X.count() +1 +>>> X.look_store() +17 +>>> X.release() +>>> X.count() +0 + + +>>> y = Y(19) +>>> y.value() +19 +>>> modify(y) +>>> look(y) +-1 +>>> store(Y(23)) +>>> Y.count() +1 +>>> Y.look_store() +23 +>>> Y.release() +>>> Y.count() +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/test/shared_ptr.cpp b/test/shared_ptr.cpp index e5f20a73..f72e6f02 100644 --- a/test/shared_ptr.cpp +++ b/test/shared_ptr.cpp @@ -1,4 +1,5 @@ // Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -8,210 +9,11 @@ #include #include #include -#include -#include "test_class.hpp" - #include -using namespace boost::python; -using boost::shared_ptr; - -typedef test_class<> X; -typedef test_class<1> Y; - -template -struct functions -{ - static int look(shared_ptr const& x) - { - return (x.get()) ? x->value() : -1; - } - - static void store(shared_ptr x) - { - storage = x; - } - - static void release_store() - { - store(shared_ptr()); - } - - static void modify(shared_ptr& x) - { - x.reset(); - } - - static shared_ptr get() { return storage; } - static shared_ptr &get1() { return storage; } - - static int look_store() - { - return look(get()); - } - - template - static void expose(C const& c) - { - def("look", &look); - def("store", &store); - def("modify", &modify); - def("identity", &identity); - def("null", &null); - - const_cast(c) - .def("look", &look) - .staticmethod("look") - .def("store", &store) - .staticmethod("store") - .def("modify", &modify) - .staticmethod("modify") - .def("look_store", &look_store) - .staticmethod("look_store") - .def("identity", &identity) - .staticmethod("identity") - .def("null", &null) - .staticmethod("null") - .def("get1", &get1, return_internal_reference<>()) - .staticmethod("get1") - .def("get", &get) - .staticmethod("get") - .def("count", &T::count) - .staticmethod("count") - .def("release", &release_store) - .staticmethod("release") - ; - } - - static shared_ptr identity(shared_ptr x) { return x; } - static shared_ptr null(T const&) { return shared_ptr(); } - - - static shared_ptr storage; -}; - -template shared_ptr functions::storage; - -struct Z : test_class<2> -{ - Z(int x) : test_class<2>(x) {} - virtual int v() { return this->value(); } -}; - -struct ZWrap : Z -{ - ZWrap(PyObject* self, int x) - : Z(x), m_self(self) {} - - - virtual int v() { return call_method(m_self, "v"); } - int default_v() { return Z::v(); } - - - PyObject* m_self; -}; - -struct YY : Y -{ - YY(int n) : Y(n) {} -}; - -struct YYY : Y -{ - YYY(int n) : Y(n) {} -}; - -shared_ptr factory(int n) -{ - return shared_ptr(n < 42 ? new Y(n) : new YY(n)); -} - -// regressions from Nicodemus - struct A - { - virtual ~A() {}; // silence compiler warnings - virtual int f() = 0; - static int call_f(shared_ptr& a) { return a->f(); } - }; - - struct B: A - { - int f() { return 1; } - }; - - boost::shared_ptr New(bool make) - { - return boost::shared_ptr( make ? new B() : 0 ); - } - - struct A_Wrapper: A - { - A_Wrapper(PyObject* self_): - A(), self(self_) {} - - int f() { - return call_method< int >(self, "f"); - } - - PyObject* self; - }; - -// ------ - -// from Neal Becker - -struct Test { - boost::shared_ptr x; -}; -// ------ - - -BOOST_PYTHON_MODULE(shared_ptr_ext) -{ - class_, boost::noncopyable>("A") - .def("call_f", &A::call_f) - .staticmethod("call_f") - ; - - // This is the ugliness required to register a to-python converter - // for shared_ptr. - objects::class_value_wrapper< - shared_ptr - , objects::make_ptr_instance,A> > - >(); - - def("New", &New); - - def("factory", factory); - - functions::expose( - class_("X", init()) - .def("value", &X::value) - ); - - functions::expose( - class_ >("Y", init()) - .def("value", &Y::value) - ); - - class_, boost::noncopyable>("YY", init()) - ; - - class_, bases >("YYY", init()) - ; - - functions::expose( - class_("Z", init()) - .def("value", &Z::value) - .def("v", &Z::v, &ZWrap::default_v) - ); - -// from Neal Becker - class_ ("Test") - .def_readonly ("x", &Test::x, "x") - ; -// ------ -} +using std::shared_ptr; +#define MODULE shared_ptr_ext +#include "shared_ptr.hpp" #include "module_tail.cpp" diff --git a/test/shared_ptr.hpp b/test/shared_ptr.hpp new file mode 100644 index 00000000..9f9a4b69 --- /dev/null +++ b/test/shared_ptr.hpp @@ -0,0 +1,206 @@ +// Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "test_class.hpp" + +using namespace boost::python; + +typedef test_class<> X; +typedef test_class<1> Y; + +template +struct functions +{ + static int look(shared_ptr const& x) + { + return (x.get()) ? x->value() : -1; + } + + static void store(shared_ptr x) + { + storage = x; + } + + static void release_store() + { + store(shared_ptr()); + } + + static void modify(shared_ptr& x) + { + x.reset(); + } + + static shared_ptr get() { return storage; } + static shared_ptr &get1() { return storage; } + + static int look_store() + { + return look(get()); + } + + template + static void expose(C const& c) + { + def("look", &look); + def("store", &store); + def("modify", &modify); + def("identity", &identity); + def("null", &null); + + const_cast(c) + .def("look", &look) + .staticmethod("look") + .def("store", &store) + .staticmethod("store") + .def("modify", &modify) + .staticmethod("modify") + .def("look_store", &look_store) + .staticmethod("look_store") + .def("identity", &identity) + .staticmethod("identity") + .def("null", &null) + .staticmethod("null") + .def("get1", &get1, return_internal_reference<>()) + .staticmethod("get1") + .def("get", &get) + .staticmethod("get") + .def("count", &T::count) + .staticmethod("count") + .def("release", &release_store) + .staticmethod("release") + ; + } + + static shared_ptr identity(shared_ptr x) { return x; } + static shared_ptr null(T const&) { return shared_ptr(); } + + + static shared_ptr storage; +}; + +template shared_ptr functions::storage; + +struct Z : test_class<2> +{ + Z(int x) : test_class<2>(x) {} + virtual int v() { return this->value(); } +}; + +struct ZWrap : Z +{ + ZWrap(PyObject* self, int x) + : Z(x), m_self(self) {} + + + virtual int v() { return call_method(m_self, "v"); } + int default_v() { return Z::v(); } + + + PyObject* m_self; +}; + +struct YY : Y +{ + YY(int n) : Y(n) {} +}; + +struct YYY : Y +{ + YYY(int n) : Y(n) {} +}; + +shared_ptr factory(int n) +{ + return shared_ptr(n < 42 ? new Y(n) : new YY(n)); +} + +// regressions from Nicodemus + struct A + { + virtual ~A() {}; // silence compiler warnings + virtual int f() = 0; + static int call_f(shared_ptr& a) { return a->f(); } + }; + + struct B: A + { + int f() { return 1; } + }; + + shared_ptr New(bool make) + { + return shared_ptr( make ? new B() : 0 ); + } + + struct A_Wrapper: A + { + A_Wrapper(PyObject* self_): + A(), self(self_) {} + + int f() { + return call_method< int >(self, "f"); + } + + PyObject* self; + }; + +// ------ + +// from Neal Becker + +struct Test { + shared_ptr x; +}; +// ------ + + +BOOST_PYTHON_MODULE(MODULE) +{ + class_, boost::noncopyable>("A") + .def("call_f", &A::call_f) + .staticmethod("call_f") + ; + + // This is the ugliness required to register a to-python converter + // for shared_ptr. + objects::class_value_wrapper< + shared_ptr + , objects::make_ptr_instance,A> > + >(); + + def("New", &New); + + def("factory", factory); + + functions::expose( + class_("X", init()) + .def("value", &X::value) + ); + + functions::expose( + class_ >("Y", init()) + .def("value", &Y::value) + ); + + class_, boost::noncopyable>("YY", init()) + ; + + class_, bases >("YYY", init()) + ; + + functions::expose( + class_("Z", init()) + .def("value", &Z::value) + .def("v", &Z::v, &ZWrap::default_v) + ); + +// from Neal Becker + class_ ("Test") + .def_readonly ("x", &Test::x, "x") + ; +// ------ +} diff --git a/test/shared_ptr.py b/test/shared_ptr.py index c70b3174..d250ae7e 100644 --- a/test/shared_ptr.py +++ b/test/shared_ptr.py @@ -5,7 +5,7 @@ >>> from shared_ptr_ext import * Test that shared_ptr can be converted to shared_ptr - + >>> Y.store(YYY(42)) >>> x = X(17) @@ -121,7 +121,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys