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:
@@ -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);
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
10
test/m1.cpp
10
test/m1.cpp
@@ -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")
|
||||
|
||||
@@ -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'
|
||||
|
||||
"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user