diff --git a/include/boost/python/converter/constructor_function.hpp b/include/boost/python/converter/constructor_function.hpp index 814aa7d763..fec356bfa0 100644 --- a/include/boost/python/converter/constructor_function.hpp +++ b/include/boost/python/converter/constructor_function.hpp @@ -7,10 +7,11 @@ namespace boost { namespace python { namespace converter { -// Declares the type of functions used to construct C++ objects for +// Declares the type of functions used to construct or destruct C++ objects for // rvalue from_python conversions. struct rvalue_from_python_stage1_data; typedef void (*constructor_function)(PyObject* source, rvalue_from_python_stage1_data*); +typedef void (*destructor_function)(rvalue_from_python_stage1_data*); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/implicit.hpp b/include/boost/python/converter/implicit.hpp index 8bbbfd5ac1..5f84bc123a 100644 --- a/include/boost/python/converter/implicit.hpp +++ b/include/boost/python/converter/implicit.hpp @@ -39,6 +39,11 @@ struct implicit // record successful construction data->convertible = storage; } + + static void destruct(rvalue_from_python_stage1_data* data) + { + reinterpret_cast(data->convertible)->~Target(); + } }; }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/registrations.hpp b/include/boost/python/converter/registrations.hpp index 7ef74e8f40..6119e361fd 100644 --- a/include/boost/python/converter/registrations.hpp +++ b/include/boost/python/converter/registrations.hpp @@ -27,6 +27,7 @@ struct rvalue_from_python_chain { convertible_function convertible; constructor_function construct; + destructor_function destruct; PyTypeObject const* (*expected_pytype)(); rvalue_from_python_chain* next; }; diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index 368adcc61d..b1464cfd3d 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -36,6 +36,7 @@ namespace registry BOOST_PYTHON_DECL void insert( convertible_function , constructor_function + , destructor_function , type_info , PyTypeObject const* (*expected_pytype)() = 0 ); @@ -45,6 +46,7 @@ namespace registry BOOST_PYTHON_DECL void push_back( convertible_function , constructor_function + , destructor_function , type_info , PyTypeObject const* (*expected_pytype)() = 0 ); diff --git a/include/boost/python/converter/rvalue_from_python_data.hpp b/include/boost/python/converter/rvalue_from_python_data.hpp index acb38f8498..8eab60c9bd 100644 --- a/include/boost/python/converter/rvalue_from_python_data.hpp +++ b/include/boost/python/converter/rvalue_from_python_data.hpp @@ -62,6 +62,7 @@ struct rvalue_from_python_stage1_data { void* convertible; constructor_function construct; + destructor_function destruct; }; // Augments rvalue_from_python_stage1_data by adding storage for @@ -132,7 +133,7 @@ template inline rvalue_from_python_data::~rvalue_from_python_data() { if (this->stage1.convertible == this->storage.bytes) - python::detail::destroy_referent(this->storage.bytes); + this->stage1.destruct(&(this->stage1)); } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/shared_ptr_from_python.hpp b/include/boost/python/converter/shared_ptr_from_python.hpp index bb2ae863ff..594a9d8ce6 100644 --- a/include/boost/python/converter/shared_ptr_from_python.hpp +++ b/include/boost/python/converter/shared_ptr_from_python.hpp @@ -25,7 +25,7 @@ struct shared_ptr_from_python { shared_ptr_from_python() { - converter::registry::insert(&convertible, &construct, type_id >() + converter::registry::insert(&convertible, &construct, &destruct, type_id >() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &converter::expected_from_python_type_direct::get_pytype #endif @@ -58,6 +58,12 @@ struct shared_ptr_from_python data->convertible = storage; } + + static void destruct(rvalue_from_python_stage1_data* data) + { + typedef SP pointer_type; + reinterpret_cast (data->convertible)->~pointer_type(); + } }; }}} // namespace boost::python::converter diff --git a/include/boost/python/enum.hpp b/include/boost/python/enum.hpp index 9631a0edc8..0b91c0da90 100644 --- a/include/boost/python/enum.hpp +++ b/include/boost/python/enum.hpp @@ -31,6 +31,7 @@ struct enum_ : public objects::enum_base static PyObject* to_python(void const* x); static void* convertible_from_python(PyObject* obj); static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data); + static void destruct(converter::rvalue_from_python_stage1_data* data); }; template @@ -40,6 +41,7 @@ inline enum_::enum_(char const* name, char const* doc ) , &enum_::to_python , &enum_::convertible_from_python , &enum_::construct + , &enum_::destruct , type_id() , doc ) @@ -89,6 +91,12 @@ void enum_::construct(PyObject* obj, converter::rvalue_from_python_stage1_dat data->convertible = storage; } +template +void enum_::destruct(converter::rvalue_from_python_stage1_data* data) +{ + reinterpret_cast(data->convertible)->~T(); +} + template inline enum_& enum_::value(char const* name, T x) { diff --git a/include/boost/python/implicit.hpp b/include/boost/python/implicit.hpp index 4d01b2fb22..efafdeb499 100644 --- a/include/boost/python/implicit.hpp +++ b/include/boost/python/implicit.hpp @@ -24,6 +24,7 @@ void implicitly_convertible(boost::type* = 0, boost::type* = 0) converter::registry::push_back( &functions::convertible , &functions::construct + , &functions::destruct , type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &converter::expected_from_python_type_direct::get_pytype diff --git a/include/boost/python/object/enum_base.hpp b/include/boost/python/object/enum_base.hpp index be34274226..3d9fc23573 100644 --- a/include/boost/python/object/enum_base.hpp +++ b/include/boost/python/object/enum_base.hpp @@ -21,6 +21,7 @@ struct BOOST_PYTHON_DECL enum_base : python::api::object , converter::to_python_function_t , converter::convertible_function , converter::constructor_function + , converter::destructor_function , type_info , const char *doc = 0 ); diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 1c28af7fc9..74c0b1b957 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -64,6 +64,7 @@ namespace registry::insert( &slot_rvalue_from_python::convertible , &slot_rvalue_from_python::construct + , &slot_rvalue_from_python::destruct , type_id() , &SlotPolicy::get_pytype ); @@ -96,6 +97,11 @@ namespace // record successful construction data->convertible = storage; } + + static void destruct(rvalue_from_python_stage1_data* data) + { + reinterpret_cast (data->convertible)->~T(); + } }; // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 9678be1cb6..b74c8234a7 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -45,6 +45,7 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( // instance, as a special case. data.convertible = objects::find_instance_impl(source, converters.target_type, converters.is_shared_ptr); data.construct = 0; + data.destruct = 0; if (!data.convertible) { for (rvalue_from_python_chain const* chain = converters.rvalue_chain; @@ -56,6 +57,7 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( { data.convertible = r; data.construct = chain->construct; + data.destruct = chain->destruct; break; } } diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index aa20c3f685..d1c9052104 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -239,12 +239,13 @@ namespace registry registration->next = found->lvalue_chain; found->lvalue_chain = registration; - insert(convert, 0, key,exp_pytype); + insert(convert, 0, 0, key,exp_pytype); } // Insert an rvalue from_python converter void insert(convertible_function convertible , constructor_function construct + , destructor_function destruct , type_info key , PyTypeObject const* (*exp_pytype)()) { @@ -255,6 +256,7 @@ namespace registry rvalue_from_python_chain *registration = new rvalue_from_python_chain; registration->convertible = convertible; registration->construct = construct; + registration->destruct = destruct; registration->expected_pytype = exp_pytype; registration->next = found->rvalue_chain; found->rvalue_chain = registration; @@ -263,6 +265,7 @@ namespace registry // Insert an rvalue from_python converter void push_back(convertible_function convertible , constructor_function construct + , destructor_function destruct , type_info key , PyTypeObject const* (*exp_pytype)()) { @@ -276,6 +279,7 @@ namespace registry rvalue_from_python_chain *registration = new rvalue_from_python_chain; registration->convertible = convertible; registration->construct = construct; + registration->destruct = destruct; registration->expected_pytype = exp_pytype; registration->next = 0; *found = registration; diff --git a/src/numpy/dtype.cpp b/src/numpy/dtype.cpp index 88a20a27b5..0bede1fe37 100644 --- a/src/numpy/dtype.cpp +++ b/src/numpy/dtype.cpp @@ -176,9 +176,13 @@ class array_scalar_converter data->convertible = storage; } + static void destruct(pyconv::rvalue_from_python_stage1_data*) + { + } + static void declare() { - pyconv::registry::push_back(&convertible, &convert, python::type_id() + pyconv::registry::push_back(&convertible, &convert, &destruct, python::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &get_pytype #endif diff --git a/src/object/enum.cpp b/src/object/enum.cpp index 4d73ee23d4..9cd4674093 100644 --- a/src/object/enum.cpp +++ b/src/object/enum.cpp @@ -192,6 +192,7 @@ enum_base::enum_base( , converter::to_python_function_t to_python , converter::convertible_function convertible , converter::constructor_function construct + , converter::destructor_function destruct , type_info id , char const *doc ) @@ -203,7 +204,7 @@ enum_base::enum_base( converters.m_class_object = downcast(this->ptr()); converter::registry::insert(to_python, id); - converter::registry::insert(convertible, construct, id); + converter::registry::insert(convertible, construct, destruct, id); } void enum_base::add_value(char const* name_, long value) diff --git a/test/Jamfile b/test/Jamfile index 7f088cf758..4edbacd34e 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -164,6 +164,7 @@ bpl-test crossmod_opaque : crossmod_opaque.py crossmod_opaque_a.cpp crossmod_opaque_b.cpp ] [ bpl-test opaque ] +[ bpl-test opaque_ref ] [ bpl-test voidptr ] [ bpl-test pickle1 ] diff --git a/test/SConscript b/test/SConscript index eaeefaca89..3e77e8aec7 100644 --- a/test/SConscript +++ b/test/SConscript @@ -88,6 +88,7 @@ for test in [('injected',), ('extract',), ('crossmod_opaque', ['crossmod_opaque_a', 'crossmod_opaque_b']), ('opaque',), + ('opaque_ref',), # ('voidptr',), ('pickle1',), ('pickle2',), diff --git a/test/a_map_indexing_suite.cpp b/test/a_map_indexing_suite.cpp index 07a0a6b977..39d3f7626d 100644 --- a/test/a_map_indexing_suite.cpp +++ b/test/a_map_indexing_suite.cpp @@ -43,6 +43,7 @@ struct AFromPython boost::python::converter::registry::push_back( &convertible, &construct, + &destruct, boost::python::type_id< A >()); } @@ -71,6 +72,11 @@ struct AFromPython #endif data->convertible = storage; } + + static void destruct(boost::python::converter::rvalue_from_python_stage1_data* data) + { + reinterpret_cast(data->convertible)->~A(); + } }; void a_map_indexing_suite() diff --git a/test/opaque_ref.cpp b/test/opaque_ref.cpp new file mode 100644 index 0000000000..2d28cf1b57 --- /dev/null +++ b/test/opaque_ref.cpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams and Gottfried Ganssauge 2003. +// 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 + +/* This class is "opaque" in the sense that it is declared, but + * we don't define it's members anywhere. */ +struct Opaque +{ +public: + Opaque(); + ~Opaque(); +}; + +void use(const Opaque& op) +{ + /* do nothing */ +} + +namespace bpl = boost::python; + +BOOST_PYTHON_MODULE(opaque_ref_ext) +{ + bpl::def ("use", &::use); +} + +# include "module_tail.cpp" diff --git a/test/opaque_ref.py b/test/opaque_ref.py new file mode 100644 index 0000000000..95ea174550 --- /dev/null +++ b/test/opaque_ref.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Copyright Gottfried Ganßauge 2003..2006. 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 opaque_ref_ext import * + + Don't do anything. The module import is already enough. + +""" +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/pytype_function.cpp b/test/pytype_function.cpp index 46cce19e65..23b334a2bf 100644 --- a/test/pytype_function.cpp +++ b/test/pytype_function.cpp @@ -40,6 +40,7 @@ struct BFromPython boost::python::converter::registry::push_back( &convertible, &construct, + &destruct, boost::python::type_id< B >() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &converter::expected_from_python_type::get_pytype//convertible to A can be converted to B @@ -65,6 +66,11 @@ struct BFromPython new (storage) B(ex()); data->convertible = storage; } + + static void destruct(boost::python::converter::rvalue_from_python_stage1_data* data) + { + reinterpret_cast(data->convertible)->~B(); + } };