[Development] On QML, ownership, QObject-trees and QSharedPointer

Stephen Kelly stephen.kelly at kdab.com
Thu May 24 21:57:40 CEST 2012


Hi Rene,

Thanks for the email. I think you raise some valid points. Some work on 
addressing them is already underway.

On Wednesday, May 23, 2012 12:25:42 Rene Jensen wrote:
> Disclaimer 3: Discussing QML seems very poisonous these days, but I
> still feel the need for a thread that focus on the good and bad with
> the current design and/or the current documentation specifically
> regarding exposing C++ to QML. Hopefully you agree and can accept that
> I bring it up on the developer list.

Yes, I think this email has the right tone and content, as others have said 
too.

>From the forum:
> Can QML gracefully handle pointers wrapped in QSharedPointer?

The answer is not yet - maybe in Qt 5.1.

> 
> So rewording the concerns to open up for (hopefully) useful comments -
> I can perhaps try to make a wiki article which adds any missing
> information:
> 
> OWNERSHIP...
> 
> These are the ownership "universes" (unless I'm mistaken):
> 
> 1) Objects created in C++ owned via the QObject parent/child tree
> e.g.: new MyGizmo.
> 2) Objects created in C++ owned via the QSharedPointer system, e.g.:
> QSharedPointer (new MyGizmo).
> 3) Objects created by QDeclarativeEngine or Javascript owned by the
> engine, e.g.: MyGizmo { ... properties ... }

Looks right to me.

> 
> Question: How can we expose objects governed by QSharedPointer to QML
> safely? I *can* guarantee the lifecycle beyond the life of my
> QDeclarativeEngine.

If you can guarantee that, then use mySharedPtr.data() as others have said.

> 
> These are the ways to transfer values/references from C++ to QML
> (let's ignore the other way around for now):
> 
> A) By calling QDeclarative::setRootContext (ownership not transferred:
> http://qt-project.org/doc/qt-4.8/qdeclarativecontext.html#setContextProperty

I think it's more common to use 

QDeclarativeEngine::rootContext()->setContextProperty() 

as Alberto said.

> D) By QML accessing a Q_PROPERTY on a C++ object (ownership?).

I guess you mean a binding?

> I assume that each time a value crosses a boundary between from C++ =>
> QML => Javascript an automatic conversion takes place. This conversion
> is probably the root of all evils, since a lot can happen with pointer
> references being smashed to either some form of null (as in
> unsuccessful C++ to QML assignment via (A) or (B) above) or
> "undefined" (like when a javascript expression tries to access a QML
> Component property) depending on factors not quite clear to me.
> 
> Question: What are the exact mechanisms that governs value conversion
> from one space to another?

Beyond what Christopher said, there's some more automation possible. We can 
add QSharedPointer<QObjectDerived> awareness to QML, as long as doing:

if (we_know_variant_contains_a_QSharedPointer_To_QObjectDerived) {
  QSharedPointer<QObject> sp;
  sp = *reinterpret_cast<QSharedPointer<QObject>*>(variant.data());
}

...is ok, which I think it is. However, we'll more likely want to make that 
possible with QWeakPointer based instances (otherwise declarative might store 
our QSharedPointer and not drop its refcount - it's a tricky issue), which 
should also be possible.

After this patch:

https://codereview.qt-project.org/#change,27070

we_know_variant_contains_a_QSharedPointer_To_QObjectDerived

will be:

QMetaType::typeFlags(variant.userType()) & QMetaType::SharedPointerToQObject

or similar. We would be able to handle 
Q_PROPERTY(QSharedPointer<QObjectDerived> ...) too.

After this stuff:

https://codereview.qt-project.org/#change,27071

... and a few more tricks adding function pointers to the QVariant::Handler, 
we would be able to handle Q_PROPERTY(QSharedPointer<SomeType> ...) too.

This is the kind of integration that I wish had been thought of for 
declarative use-cases long ago and designed into QVariant in Qt 5 with the 
hybrid QML application use-cases in mind. 

The needs QtDeclarative has needs for non-type-safety and conversions are 
mostly separate and internal, so it's not as easy as it could be to use user-
defined types and containers and QVariants with QML, like automatic handling 
of QList<int>, QVector<int> and generally Container<T>. Maybe we can make this 
stuff better in 5.1 though... We'll have to see if it works and the API can be 
extended for it in a maintainable way.

Handling QObject derived types might be easily handled too (currently it 
introduces several inconveniences for hybrid apps):

https://codereview.qt-project.org/#change,13006

https://codereview.qt-project.org/#change,13007

https://codereview.qt-project.org/#change,19113

> 
> COLLECTIONS...
> 
> Collections (QList, QMap, QHash, QSet) of object references
> constitutes a special scenario which in my view is less that ideally
> solved. I would love a much simpler and more intuitive way to expose
> those to QML. But given that this topic is way too large, I don't want
> to bring it up here, although it does belong.

I have a working patch , but again, it was already pushed back to 5.1:

https://bugreports.qt-project.org/browse/QTBUG-23566



I'm still not 100% certain if this stuff can be done correctly and efficiently 
in 5.1, so that's why I've said 'maybe' so many times in this mail :). Another 
reason for the 'maybe's is that maybe we'll find that my plans and ideas are 
no good.

Thanks,

-- 
Stephen Kelly <stephen.kelly at kdab.com> | Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
www.kdab.com || Germany +49-30-521325470 || Sweden (HQ) +46-563-540090
KDAB - Qt Experts - Platform-Independent Software Solutions
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.qt-project.org/pipermail/development/attachments/20120524/fa1aeb43/attachment.sig>


More information about the Development mailing list