diff --git a/src/pya/pya/pyaConvert.cc b/src/pya/pya/pyaConvert.cc index d80af95e9..017d030e2 100644 --- a/src/pya/pya/pyaConvert.cc +++ b/src/pya/pya/pyaConvert.cc @@ -533,8 +533,13 @@ PyObject *c2python_func::operator() (const tl::Variant &c) const gsi::ClassBase *cls = c.gsi_cls (); if (cls) { - void *obj = const_cast (c.to_user ()); - return object_to_python (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false); + if (! c.user_is_ref () && cls->is_managed ()) { + void *obj = c.user_unshare (); + return object_to_python (obj, 0, c.user_cls ()->gsi_cls (), true, c.user_is_const (), false, false); + } else { + void *obj = const_cast (c.to_user ()); + return object_to_python (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false); + } } else { // not a known type -> return nil Py_RETURN_NONE; diff --git a/src/rba/rba/rbaConvert.cc b/src/rba/rba/rbaConvert.cc index b803b6450..2a05a69cf 100644 --- a/src/rba/rba/rbaConvert.cc +++ b/src/rba/rba/rbaConvert.cc @@ -287,8 +287,13 @@ VALUE c2ruby (const tl::Variant &c) } else if (c.is_user ()) { const gsi::ClassBase *cls = c.gsi_cls (); if (cls) { - void *obj = const_cast (c.to_user ()); - return object_to_ruby (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false); + if (! c.user_is_ref () && cls->is_managed ()) { + void *obj = c.user_unshare (); + return object_to_ruby (obj, 0, c.user_cls ()->gsi_cls (), true, c.user_is_const (), false, false); + } else { + void *obj = const_cast (c.to_user ()); + return object_to_ruby (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false); + } } else { // not a known type -> return nil return Qnil; diff --git a/src/tl/tl/tlObject.cc b/src/tl/tl/tlObject.cc index b28b0958a..fd4f6aaf4 100644 --- a/src/tl/tl/tlObject.cc +++ b/src/tl/tl/tlObject.cc @@ -227,6 +227,11 @@ const Object *WeakOrSharedPtr::get () const return mp_t; } +void WeakOrSharedPtr::unshare () +{ + m_is_shared = false; +} + void WeakOrSharedPtr::reset_object () { tl::MutexLocker locker (&lock ()); diff --git a/src/tl/tl/tlObject.h b/src/tl/tl/tlObject.h index 9bea96ed4..0157c6887 100644 --- a/src/tl/tl/tlObject.h +++ b/src/tl/tl/tlObject.h @@ -197,6 +197,12 @@ public: */ void detach_from_all_events (); + /** + * @brief Unshares the object + * This will turn a shared reference into a weak one. + */ + void unshare (); + /** * @brief Indicates that this object is an event * This property is intended for internal use only. @@ -401,6 +407,9 @@ public: { // .. nothing yet .. } + +private: + using weak_or_shared_ptr::unshare; }; /** @@ -429,6 +438,9 @@ public: { // .. nothing yet .. } + +private: + using weak_or_shared_ptr::unshare; }; } diff --git a/src/tl/tl/tlVariant.cc b/src/tl/tl/tlVariant.cc index 28d476282..1811606fb 100644 --- a/src/tl/tl/tlVariant.cc +++ b/src/tl/tl/tlVariant.cc @@ -2709,6 +2709,21 @@ void *Variant::user_take () return obj; } +void *Variant::user_unshare () const +{ + tl_assert (is_user () && ! user_is_ref ()); + + if (m_type == t_user) { + Variant *nc_this = const_cast (this); + nc_this->m_var.mp_user.shared = false; + } else if (m_type == t_user_ref) { + tl::WeakOrSharedPtr *wptr = const_cast (reinterpret_cast (m_var.mp_user_ref.ptr)); + wptr->unshare (); + } + + return const_cast (to_user ()); +} + void Variant::user_assign (const tl::Variant &other) { tl_assert (is_user ()); diff --git a/src/tl/tl/tlVariant.h b/src/tl/tl/tlVariant.h index 4b12a892a..762a49eb9 100644 --- a/src/tl/tl/tlVariant.h +++ b/src/tl/tl/tlVariant.h @@ -891,6 +891,13 @@ public: */ void *user_take (); + /** + * @brief Takes the user object and releases ownership by the variant + * This method is const as it does not change the value, but the ownership of + * the contained object. The object must not be "user_is_ref". + */ + void *user_unshare () const; + /** * @brief Assigns the object stored in other to self *