Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an explicit destructor function argument to registry::push_back() #170

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/boost/python/converter/constructor_function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 5 additions & 0 deletions include/boost/python/converter/implicit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ struct implicit
// record successful construction
data->convertible = storage;
}

static void destruct(rvalue_from_python_stage1_data* data)
{
reinterpret_cast<Target*>(data->convertible)->~Target();
}
};

}}} // namespace boost::python::converter
Expand Down
1 change: 1 addition & 0 deletions include/boost/python/converter/registrations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
2 changes: 2 additions & 0 deletions include/boost/python/converter/registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace registry
BOOST_PYTHON_DECL void insert(
convertible_function
, constructor_function
, destructor_function
, type_info
, PyTypeObject const* (*expected_pytype)() = 0
);
Expand All @@ -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
);
Expand Down
3 changes: 2 additions & 1 deletion include/boost/python/converter/rvalue_from_python_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -132,7 +133,7 @@ template <class T>
inline rvalue_from_python_data<T>::~rvalue_from_python_data()
{
if (this->stage1.convertible == this->storage.bytes)
python::detail::destroy_referent<ref_type>(this->storage.bytes);
this->stage1.destruct(&(this->stage1));
}

}}} // namespace boost::python::converter
Expand Down
8 changes: 7 additions & 1 deletion include/boost/python/converter/shared_ptr_from_python.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct shared_ptr_from_python
{
shared_ptr_from_python()
{
converter::registry::insert(&convertible, &construct, type_id<SP<T> >()
converter::registry::insert(&convertible, &construct, &destruct, type_id<SP<T> >()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &converter::expected_from_python_type_direct<T>::get_pytype
#endif
Expand Down Expand Up @@ -58,6 +58,12 @@ struct shared_ptr_from_python

data->convertible = storage;
}

static void destruct(rvalue_from_python_stage1_data* data)
{
typedef SP<T> pointer_type;
reinterpret_cast<pointer_type*> (data->convertible)->~pointer_type();
}
};

}}} // namespace boost::python::converter
Expand Down
8 changes: 8 additions & 0 deletions include/boost/python/enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class T>
Expand All @@ -40,6 +41,7 @@ inline enum_<T>::enum_(char const* name, char const* doc )
, &enum_<T>::to_python
, &enum_<T>::convertible_from_python
, &enum_<T>::construct
, &enum_<T>::destruct
, type_id<T>()
, doc
)
Expand Down Expand Up @@ -89,6 +91,12 @@ void enum_<T>::construct(PyObject* obj, converter::rvalue_from_python_stage1_dat
data->convertible = storage;
}

template <class T>
void enum_<T>::destruct(converter::rvalue_from_python_stage1_data* data)
{
reinterpret_cast<T*>(data->convertible)->~T();
}

template <class T>
inline enum_<T>& enum_<T>::value(char const* name, T x)
{
Expand Down
1 change: 1 addition & 0 deletions include/boost/python/implicit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void implicitly_convertible(boost::type<Source>* = 0, boost::type<Target>* = 0)
converter::registry::push_back(
&functions::convertible
, &functions::construct
, &functions::destruct
, type_id<Target>()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &converter::expected_from_python_type_direct<Source>::get_pytype
Expand Down
1 change: 1 addition & 0 deletions include/boost/python/object/enum_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
Expand Down
6 changes: 6 additions & 0 deletions src/converter/builtin_converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace
registry::insert(
&slot_rvalue_from_python<T,SlotPolicy>::convertible
, &slot_rvalue_from_python<T,SlotPolicy>::construct
, &slot_rvalue_from_python<T,SlotPolicy>::destruct
, type_id<T>()
, &SlotPolicy::get_pytype
);
Expand Down Expand Up @@ -96,6 +97,11 @@ namespace
// record successful construction
data->convertible = storage;
}

static void destruct(rvalue_from_python_stage1_data* data)
{
reinterpret_cast<T*> (data->convertible)->~T();
}
};

// identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
Expand Down
2 changes: 2 additions & 0 deletions src/converter/from_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/converter/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)())
{
Expand All @@ -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;
Expand All @@ -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)())
{
Expand All @@ -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;
Expand Down
6 changes: 5 additions & 1 deletion src/numpy/dtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>()
pyconv::registry::push_back(&convertible, &convert, &destruct, python::type_id<T>()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &get_pytype
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/object/enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -203,7 +204,7 @@ enum_base::enum_base(

converters.m_class_object = downcast<PyTypeObject>(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)
Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]
Expand Down
1 change: 1 addition & 0 deletions test/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ for test in [('injected',),
('extract',),
('crossmod_opaque', ['crossmod_opaque_a', 'crossmod_opaque_b']),
('opaque',),
('opaque_ref',),
# ('voidptr',),
('pickle1',),
('pickle2',),
Expand Down
6 changes: 6 additions & 0 deletions test/a_map_indexing_suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct AFromPython
boost::python::converter::registry::push_back(
&convertible,
&construct,
&destruct,
boost::python::type_id< A >());
}

Expand Down Expand Up @@ -71,6 +72,11 @@ struct AFromPython
#endif
data->convertible = storage;
}

static void destruct(boost::python::converter::rvalue_from_python_stage1_data* data)
{
reinterpret_cast<A*>(data->convertible)->~A();
}
};

void a_map_indexing_suite()
Expand Down
31 changes: 31 additions & 0 deletions test/opaque_ref.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/python/reference_existing_object.hpp>
# include <boost/python/def.hpp>
# include <boost/python/module.hpp>
# include <boost/python/return_value_policy.hpp>

/* 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"
26 changes: 26 additions & 0 deletions test/opaque_ref.py
Original file line number Diff line number Diff line change
@@ -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)
6 changes: 6 additions & 0 deletions test/pytype_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<A>::get_pytype//convertible to A can be converted to B
Expand All @@ -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<B*>(data->convertible)->~B();
}
};


Expand Down