[Development] QQmlEngine and ObjectOwnership

Massimo Callegari massimocallegari at yahoo.it
Tue Apr 28 14:46:29 CEST 2015


Hi Bo,
well, I guess it all depends on what kind of application you're writing.

I just wanted to share my specific(?) case so if someone stumbles on it, they can find the solution out of the box :)

Mine is probably a poor experience with the QML world, where C++ still gives me that safety to sleep at night :)

I am wondering though, in a multi-context application, where you have a MainView.qml with a big
Loader that changes context when clicking on some buttons, where do you place "shared" Items that
need to be accessed by a context that don't know anything about the other contexts ?

That's why I prefer to have a solid C++ ground where I can access my classes all across QML contexts.

For now I take QML as an awesome place to design a UI and perform small logics and animations.
Maybe in the future I will change my mind !

Anyway, let there be mighty dragons ! :)

Massimo



----- Messaggio originale -----
Da: Bo Thorsen <bo at vikingsoft.eu>
A: Massimo Callegari <massimocallegari at yahoo.it>; "development at qt-project.org" <development at qt-project.org>
Cc: 
Inviato: Martedì 28 Aprile 2015 14:25
Oggetto: Re: [Development] QQmlEngine and ObjectOwnership

On 04/28/2015 12:08 PM, Massimo Callegari wrote:

> Hi everyone,
>
> I want to share my experience with the garbage collection of registered classes through qmlRegisterType.
>
> I got crazy to understand why my application was randomly crashing and I hope this will help others in the future.
>
> Basically if you want to expose a C++ class in the QML world, you do something like:
>
> qmlRegisterType<MyClass>("com.myapp.classes", 1, 0, "MyClass");
>
> Then you can use the class methods exposed with Q_PROPERTY in QML like this: MyClass.myProperty
>
> The thing is that when dealing with class pointers, the QML engine performs garbage collection of the exposed classes when it no longer needs them.
>
> If your classes are created in C++ (new MyClass()) at some point in the C++ code, you will find that the class has been destroyed by QML !! This causes a bunch of segFaults like there is no tomorrow.
>
> So, after getting crazy to discover this, I discovered also that there is a method of QQmlEngine to
> assign the ownership of a class:
>
> QQmlEngine::setObjectOwnership(myNewClass, QQmlEngine::CppOwnership);
>
>
> After adding this simple line after a "myNewClass = new MyClass()", everything started to working properly.
>
> Note that in my application, classes created in C++ exist as long as the application lives.
> Now, I found pretty counter-intuitive that a class created in C++ is actually owned by QML (
> QQmlEngine::JavaScriptOwnership)
>
>
> I believe the default ownership should be CppOwnership if the class is created in C++ and then, in case, the developer can do the other way around, letting QML to handle the destruction of QObjects.

Hi Massimo,

No, the default is correct. When you expose types to the QML engine, it 
will construct and destruct objects of your types as it wants to.

If you want to have objects that are not controlled by the engine, you 
can either use qmlRegisterUncreatableType or expose object as context 
properties with viewer->rootContext()->setContextProperty(). The 
uncreatable types are useful if you have an object that returns an 
object of this type. Remember to set the parent of those objects.

The "fix" you found is actually the proper way to do this, if you want 
to create QML objects and control the deletion of them. This is not 
normally what you would do, so it should not be the default.

In the area where you are here - dynamic creation of QML objects - there 
be mighty dragons. Careful where you go with this. It is much easier to 
avoid this area completely by using Loader objects and registering 
global objects to the contexts.

Bo Thorsen,
Director, Viking Software.

-- 
Viking Software
Qt and C++ developers for hire
http://www.vikingsoft.eu



More information about the Development mailing list