2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-26 18:52:26 +00:00

More smart pointer handling

[SVN r15069]
This commit is contained in:
Dave Abrahams
2002-08-23 18:07:27 +00:00
parent 0b33d1800d
commit bcaa1043ea
7 changed files with 97 additions and 27 deletions

View File

@@ -52,15 +52,17 @@ namespace detail
// to the type of holder that must be created. The 3rd argument is a
// reference to the Python type object to be created.
template <class T, class Holder>
static inline void register_copy_constructor(mpl::bool_t<true> const&, Holder*, object const& obj, T* = 0)
static inline void register_copy_constructor(mpl::bool_t<true> const&, Holder*, T* = 0)
{
objects::class_wrapper<T,Holder> x(obj);
force_instantiate(objects::class_wrapper<T,Holder>());
Holder::register_();
}
// Tag dispatched to have no effect.
template <class T, class Holder>
static inline void register_copy_constructor(mpl::bool_t<false> const&, Holder*, object const&, T* = 0)
static inline void register_copy_constructor(mpl::bool_t<false> const&, Holder*, T* = 0)
{
Holder::register_();
}
template <class T> int assert_default_constructible(T const&);
@@ -331,7 +333,7 @@ inline void class_<T,X1,X2,X3>::register_() const
detail::register_copy_constructor<T>(
mpl::bool_t<is_copyable>()
, objects::select_holder<T,held_type>((held_type*)0).get()
, *this);
);
}

View File

@@ -24,6 +24,10 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable
virtual void* holds(type_info) = 0;
void install(PyObject* inst) throw();
// Register any converters associated with this Holder
static inline void register_() {}
private:
instance_holder* m_next;
};

View File

@@ -8,26 +8,37 @@
# include <boost/python/handle.hpp>
# include <boost/python/to_python_converter.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/ref.hpp>
namespace boost { namespace python { namespace objects {
template <class T, class Holder>
struct class_wrapper
: to_python_converter<T,class_wrapper<T,Holder> >
template <class Src, class Holder>
struct copy_construct_instance
{
class_wrapper(object const& type_)
: m_class_object_keeper(type_)
static Holder* execute(PyObject* instance, Src const& x)
{
assert(type_.ptr()->ob_type == (PyTypeObject*)class_metatype().get());
m_class_object = (PyTypeObject*)type_.ptr();
return new Holder(instance, cref(x));
}
static PyObject* convert(T const& x)
};
// Used to convert objects of type Src to wrapped C++ classes by
// building a new instance object and installing a Holder constructed
// from the Src object.
template <class Src, class Holder, class MakeHolder = copy_construct_instance<Src,Holder> >
struct class_wrapper
: to_python_converter<Src,class_wrapper<Src,Holder,MakeHolder> >
{
static PyObject* convert(Src const& x)
{
// Get the class object associated with the wrapped type
typedef typename Holder::value_type value_type;
PyTypeObject* class_object = converter::registered<value_type>::converters.class_object;
// Don't call the type directly to do the construction, since
// that would require the registration of an appropriate
// __init__ function.
PyObject* raw_result = m_class_object->tp_alloc(m_class_object, 0);
PyObject* raw_result = class_object->tp_alloc(class_object, 0);
if (raw_result == 0)
return 0;
@@ -38,7 +49,7 @@ struct class_wrapper
// Build a value_holder to contain the object using the copy
// constructor
Holder* p = new Holder(raw_result, cref(x));
Holder* p = MakeHolder::execute(raw_result, x);
// Install it in the instance
p->install(raw_result);
@@ -46,15 +57,8 @@ struct class_wrapper
// Return the new result
return result.release();
}
private:
object m_class_object_keeper;
static PyTypeObject* m_class_object;
};
template <class T, class Holder>
PyTypeObject* class_wrapper<T,Holder>::m_class_object;
}}} // namespace boost::python::objects
#endif // CLASS_WRAPPER_DWA20011221_HPP

View File

@@ -16,6 +16,7 @@
# include <boost/python/object/inheritance.hpp>
# include <boost/python/object/find_instance.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/python/object/class_wrapper.hpp>
# include <boost/python/pointee.hpp>
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/python/detail/preprocessor.hpp>
@@ -34,13 +35,26 @@ namespace boost { namespace python { namespace objects {
template <class Pointer, class Value>
struct pointer_holder : instance_holder
{
typedef Value value_type;
pointer_holder(Pointer);
static void register_();
// Forward construction to the held object
# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/pointer_holder.hpp>, 1))
# include BOOST_PP_ITERATE()
private: // types
struct construct_from_pointer
{
static pointer_holder* execute(PyObject*, Pointer x)
{
return new pointer_holder(x);
}
};
private: // required holder implementation
void* holds(type_info);
@@ -54,9 +68,14 @@ struct pointer_holder_back_reference : instance_holder
private:
typedef typename python::pointee<Pointer>::type held_type;
public:
typedef Value value_type;
// Not sure about this one -- can it work? The source object
// undoubtedly does not carry the correct back reference pointer.
pointer_holder_back_reference(Pointer);
static void register_();
// Forward construction to the held object
# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/pointer_holder.hpp>, 2))
# include BOOST_PP_ITERATE()
@@ -76,12 +95,29 @@ inline pointer_holder<Pointer,Value>::pointer_holder(Pointer p)
{
}
template <class Pointer, class Value>
inline void pointer_holder<Pointer,Value>::register_()
{
python::detail::force_instantiate(class_wrapper<Pointer,pointer_holder,construct_from_pointer>());
python::detail::force_instantiate(instance_finder<Pointer>::registration);
}
template <class Pointer, class Value>
inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_reference(Pointer p)
: m_p(p)
{
}
template <class Pointer, class Value>
inline void pointer_holder_back_reference<Pointer,Value>::register_()
{
// not implemented at least until we solve the back reference issue mentioned above.
// python::detail::force_instantiate(class_wrapper<Pointer,pointer_holder_back_reference>());
python::detail::force_instantiate(instance_finder<Pointer>::registration);
python::detail::force_instantiate(instance_finder<held_type>::registration);
}
template <class Pointer, class Value>
void* pointer_holder<Pointer, Value>::holds(type_info dst_t)
{
@@ -142,9 +178,7 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t)
: m_p(new held_type(
p BOOST_PP_COMMA_IF(N) BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
))
{
python::detail::force_instantiate(instance_finder<held_type>::registration);
}
{}
# undef N

View File

@@ -29,6 +29,8 @@ namespace boost { namespace python { namespace objects {
template <class Held>
struct value_holder : instance_holder
{
typedef Held value_type;
// Forward construction to the held object
# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/value_holder.hpp>, 1))
# include BOOST_PP_ITERATE()
@@ -43,6 +45,10 @@ struct value_holder : instance_holder
template <class Held, class BackReferenceType>
struct value_holder_back_reference : instance_holder
{
typedef Held value_type;
static void register_();
// Forward construction to the held object
# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/value_holder.hpp>, 2))
# include BOOST_PP_ITERATE()
@@ -79,6 +85,12 @@ void* value_holder_back_reference<Held,BackReferenceType>::holds(
return find_static_type(x, src_t, dst_t);
}
template <class Held, class BackReferenceType>
void value_holder_back_reference<Held,BackReferenceType>::register_()
{
python::detail::force_instantiate(instance_finder<BackReferenceType>::registration);
}
}}} // namespace boost::python::objects
# endif // VALUE_HOLDER_DWA20011215_HPP
@@ -119,7 +131,6 @@ void* value_holder_back_reference<Held,BackReferenceType>::holds(
BOOST_PP_REPEAT(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
)
{
python::detail::force_instantiate(instance_finder<BackReferenceType>::registration);
}
# undef N

View File

@@ -190,7 +190,11 @@ A take_a(A const& a) { return a; }
B take_b(B& b) { return b; }
C take_c(C* c) { return *c; }
D take_d(D* const& d) { return *d; }
D take_d_shared_ptr(boost::shared_ptr<D> d) { return *d; }
boost::shared_ptr<A> d_factory() { return boost::shared_ptr<B>(new D); }
BOOST_PYTHON_MODULE_INIT(m1)
{
using namespace boost::python;
@@ -237,6 +241,10 @@ BOOST_PYTHON_MODULE_INIT(m1)
.def("take_b", take_b)
.def("take_c", take_c)
.def("take_d", take_d)
.def("take_d_shared_ptr", take_d_shared_ptr)
.def("d_factory", d_factory)
;
class_<A, shared_ptr<A> >("A")

View File

@@ -158,6 +158,13 @@ are a complicated constructor and member function, respectively.
>>> take_d(d).name()
'D'
>>> take_d_shared_ptr(d).name()
'D'
>>> d_as_a = d_factory()
>>> dd = take_d(d_as_a)
>>> dd.name()
'D'
"""