[Development] QQmlEngine and ObjectOwnership

Bo Thorsen bo at vikingsoft.eu
Tue Apr 28 14:25:52 CEST 2015


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