Memory management of objects handed back to QML
-
I have a helper class that maintains a little context that I'd like to pass back to qml through an invokable as a pointer. What's the easiest way to cleanup the object when the javascript funcTion is done with it? I'm hoping there's a Qt'ism for this as I'd rather not have to implemet a clean up function to delete it from qml.
Thanks
-
QML already does this. A QObject which is returned to QML from an invokable function as a return value has its ownership semantics set to JavaScriptOwnership if it has not previously been explicitly set to CppOwnership. Thus, when you've finished using it, the garbage collector should be able to collect it (assuming no other JS references to it exist).
Calling gc() occasionally during debugging/development and using qDebug() statements in your dtors (or console.log()s in Component.onDestruction handlers) is a good way to trace deletions, however be aware that QObject deletions triggered by the garbage collector are deleteLater()s, so you'll need to process deferred deletion events before you'll see those dtors show up.
-
Thanks. Interesting I didn't know this. Is it documented somewhere? My only concern is that someone could call the method directly in c++ where there would be no GC. Would returning a QSharedPointer solve both cases? I've been trying this method, but I keep getting a seg fault deep down in Qt during atomic deref in ASM.
-
It is documented, although perhaps not conspicuously enough. See the ObjectOwnership enum docs at http://doc.qt.nokia.com/4.7-snapshot/qdeclarativeengine.html for the description of the semantics.
If they call the method directly in C++ you're right - you'd have to manually manage the lifetime of the object returned. Furthermore, even in JS you have no guarantee that the garbage collector will ever run (eg, if the system doesn't get low on memory, a garbage collect won't be triggered) and thus you'd either have to manually call gc() or risk having the dtor of the object not called until the application exits (the gc() is always run just prior to application exit, at least in QtQuick2).
A QSharedPointer probably wouldn't work, as far as I know. I don't actually know how QML would handle that case (it may actually use the automatic conversion to QObject* and manage the lifetime without the locking/etc provided by the shared pointer, which could cause the segfault you're seeing - although that's all surmise and could very well be wrong).
-
[quote author="chriadam" date="1332833133"]QML already does this. A QObject which is returned to QML from an invokable function as a return value has its ownership semantics set to JavaScriptOwnership if it has not previously been explicitly set to CppOwnership. [/quote]
How does this work considering QObject can't be returned by value?
-
[quote author="chriadam" date="1332833133"]QML already does this. A QObject which is returned to QML from an invokable function as a return value has its ownership semantics set to JavaScriptOwnership if it has not previously been explicitly set to CppOwnership. [/quote]
How does this work considering QObject can't be returned by value?