2
0
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:
Dave Abrahams
2002-02-03 05:03:05 +00:00
parent 0a9d5f680f
commit 262396d48b
5 changed files with 137 additions and 7 deletions

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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(

View File

@@ -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