mirror of
https://github.com/boostorg/python.git
synced 2026-01-23 17:52:17 +00:00
Object life support
[SVN r12662]
This commit is contained in:
1
Jamfile
1
Jamfile
@@ -20,6 +20,7 @@ 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
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
# define RETURN_INTERNAL_REFERENCE_DWA2002131_HPP
|
||||
|
||||
# include <boost/python/default_call_policies.hpp>
|
||||
# include <boost/python/object/life_support.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/python/reference_existing_object.hpp>
|
||||
# include <boost/python/to_python_indirect.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -28,18 +31,39 @@ struct internal_reference_to_python_generator
|
||||
{
|
||||
typedef typename mpl::select_type<
|
||||
!is_object<T>::value
|
||||
, internal_reference_to_python<T>
|
||||
, detail::return_internal_reference_requires_a_pointer_or_reference_return_type
|
||||
, to_python_indirect<T, detail::make_reference_holder>
|
||||
, detail::return_internal_reference_requires_a_pointer_or_reference_return_type<T>
|
||||
>::type type;
|
||||
};
|
||||
};
|
||||
|
||||
template <std::size_t owner_arg, class Base = default_call_policies>
|
||||
template <std::size_t owner_arg = 1, class Base = default_call_policies>
|
||||
struct return_internal_reference : Base
|
||||
{
|
||||
typedef wrap_internal_reference<owner_arg> result_converter;
|
||||
typedef reference_existing_object result_converter;
|
||||
static PyObject* postcall(PyObject* args, PyObject* result);
|
||||
};
|
||||
|
||||
template <std::size_t owner_arg, class Base>
|
||||
PyObject* return_internal_reference<owner_arg,Base>::postcall(PyObject* args_, PyObject* result)
|
||||
{
|
||||
PyObject* patient = PyTuple_GetItem(args_, owner_arg - 1);
|
||||
if (patient != 0) // Make sure the argument was in range.
|
||||
{
|
||||
result = Base::postcall(args_,result);
|
||||
if (result != 0)
|
||||
{
|
||||
if (python::objects::make_nurse_and_patient(result, patient) == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Py_XDECREF(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // RETURN_INTERNAL_REFERENCE_DWA2002131_HPP
|
||||
|
||||
99
src/object/life_support.cpp
Normal file
99
src/object/life_support.cpp
Normal file
@@ -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.
|
||||
#include <boost/python/object/life_support.hpp>
|
||||
#include <boost/python/detail/none.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
struct life_support
|
||||
{
|
||||
PyObject_HEAD
|
||||
PyObject* patient;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
static void
|
||||
life_support_dealloc(PyObject* self)
|
||||
{
|
||||
self->ob_type->tp_free(self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
life_support_call(PyObject *self, PyObject *arg, PyObject *kw)
|
||||
{
|
||||
// Let the patient die now
|
||||
Py_XDECREF(((life_support*)self)->patient);
|
||||
// Also let the weak reference die. This probably kills us.
|
||||
Py_XDECREF(PyTuple_GET_ITEM(arg, 0));
|
||||
return detail::none();
|
||||
}
|
||||
}
|
||||
|
||||
PyTypeObject life_support_type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"Boost.Python.life_support",
|
||||
sizeof(life_support),
|
||||
0,
|
||||
life_support_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, //(reprfunc)func_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
life_support_call, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, // PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, // PyObject_GenericSetAttr, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */
|
||||
0, /* tp_doc */
|
||||
0, // (traverseproc)func_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, //offsetof(PyLife_SupportObject, func_weakreflist), /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, // func_memberlist, /* tp_members */
|
||||
0, //func_getsetlist, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
0,
|
||||
0 /* tp_new */
|
||||
};
|
||||
|
||||
int make_nurse_and_patient(PyObject* nurse, PyObject* patient)
|
||||
{
|
||||
life_support* system = PyObject_New(life_support, &life_support_type);
|
||||
if (!system)
|
||||
return -1;
|
||||
|
||||
// We're going to leak this reference, but don't worry; the
|
||||
// life_support system decrements it when the nurse dies.
|
||||
PyObject* weakref = PyWeakref_NewRef(nurse, (PyObject*)system);
|
||||
if (!weakref)
|
||||
{
|
||||
Py_XDECREF(system);
|
||||
return -1;
|
||||
}
|
||||
|
||||
system->patient = patient;
|
||||
Py_XINCREF(patient); // hang on to the patient until death
|
||||
return 0;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
#include <boost/python/manage_new_object.hpp>
|
||||
#include <boost/python/reference_existing_object.hpp>
|
||||
#include <boost/python/return_internal_reference.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/mpl/type_list.hpp>
|
||||
|
||||
@@ -75,7 +75,7 @@ BOOST_PYTHON_MODULE_INIT(test_pointer_adoption_ext)
|
||||
|
||||
class_<A>()
|
||||
.def("content", &A::content)
|
||||
.def("get_inner", &A::get_inner, return_value_policy<reference_existing_object>())
|
||||
.def("get_inner", &A::get_inner, return_internal_reference<>())
|
||||
)
|
||||
|
||||
.add(
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
>>> a.content()
|
||||
'with an exposed reference'
|
||||
|
||||
>>> innards = None
|
||||
# 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
|
||||
|
||||
"""
|
||||
def run(args = None):
|
||||
import sys
|
||||
|
||||
Reference in New Issue
Block a user