Ownership between Qt C++ and QML
-
Hi friends,
I meet a problem about ownership these days, and i try to find out the answer, but after some search and discussing, i still have questions. So please help me out. Thank you!
The question i meet is, i try to use a list in QML, which type is QList<QObject*>, and i doubt that when this object will be destroyed.I find this in Qt document:
[quote]Ownership controls whether or not QML automatically destroys the QObject when the object is garbage collected by the JavaScript engine. The two ownership options are: QDeclarativeEngine::CppOwnership & QDeclarativeEngine::JavaScriptOwnership[/quote]So my first question is, what does "object" mean, it just mean QObject or objects inherit QObject ?
In my opinion, object should be QObject or objects inherit QObject. But with the example below:// header file
@class CMyData: public QObject
{
Q_OBJECT
Q_PROPERTY(int id READ id)public:
explicit CMyData(QObject *parent = 0): QObject(parent) {}
CMyData(const CMyData& other): QObject() {}
~CMyData() {
qDebug() << "haha";
}
int id() { return 11; }
};class CEngine : public QObject
{
Q_OBJECT
public:
explicit CEngine(QObject *parent = 0);Q_INVOKABLE QObjectList getDataList(); QObject* obj1; QObject* obj2; QObjectList* iList;
};@
// source file
@CEngine::CEngine(QObject *parent) :
QObject(parent)
{
obj1 = new CMyData;
obj2 = new CMyData;iList = new QObjectList;
}
QObjectList CEngine::getDataList()
{
iList->append(obj1);
iList->append(obj2);return *iList;
}@
The obj1 and obj2 will be destroy under the garbage collection. So, what's happend ? And i don't think QList<QObject*> is the object will be destroy after collected by javascript . But how about the QObject(s) in it ?
-
I believe this is the sort of confusion that "QDeclarativeListProperty":http://doc.qt.nokia.com/4.7-snapshot/qdeclarativelistproperty.html is intended to solve.
The paragraph after the one you quoted in the QDeclarativeEngine docs
http://doc.qt.nokia.com/4.7-snapshot/qdeclarativeengine.html#ObjectOwnership-enum
says that objects returned from method calls will default to JavaScript ownership. Yes, QObjects includes QObject derived classes. -
Hi aalpert, thanks for the reply. I'll take a look at QDeclarativeListProperty. And let's go to the question i put in thread, can you tell me how about QList<QObject*> ? I return one instance of the QList<QObject*>,let's call it "myList", it's not a class inherit QObject, but the objects inside it destroyed by the javascript. So, if any QObject derived class's instance will be destroy by javascript when js run destroy after garbage collection? And there comes another question, if i change the ownership of the parent object, will the children's ownership be changed? Thank you again :D
-
myList is returning a number of QObjects to Javascript. As they were returned from a method called from Javascript, they have javascript ownership. They will be garbage collected by javascript.
If you manually change the ownership of the parent object, chlidren are not affected.
-
-
I don't quite agree according to my experimentation. If I add a new function into above engine code like:
@ Q_INVOKABLE CMyData* getData() {
return new CMyData();
}@
then no matter how many times qml calls this getData() function, the desctruction of CMyData will not happen at all.
But if you change the return type of CMyData* to QObject* , everything works as it should be: "haha" printed out when calls the getData() many times.- another problem is we could only define QObject* as the parameter of Q_INVOKABLE function, even int*, int&, QObject&, CMyData*, CMyData& can not be recongnized.
-
-
Hi aalpert, i just do a test about the garbage collection. If the return value of my method call is a custom type(which derived QObject), the QML not change it's ownership unless i change it explicitly in my C++ code. Anything wrong ? So, maybe it's the same question with Alex Liu. Thank you . :-)
-
Hi aalpert & Alex, i do more test on this. And the usecases are:
I use QList<MyData*> instead of QList<QObject*>, the MyData won't be destroyed, and also can not be recognized. What's wrong with me ?
// Some code
@
QList<CMyData*> CEngine::getData()
{
QList<CMyData*> myList;
CMyData *data = new CMyData();
QDeclarativeEngine::setObjectOwnership(data, QDeclarativeEngine::JavaScriptOwnership);
myList.append(data);return myList;
}@
@int main(int argc, char *argv[])
{
QApplication app(argc, argv);qmlRegisterType<CMyData>("CMyData", 1, 0, "CMyData"); qRegisterMetaType<CMyData>("CMyData"); CEngine *engine = new CEngine; QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.rootContext()->setContextProperty("engine", engine); viewer.setMainQmlFile(QLatin1String("qml/test/main.qml")); viewer.showExpanded(); return app.exec();
}@
// In qml file
@
...
function getData()
{
// Trigger garbage collection
for(var i=0; i<1000; i++)
{
var dataList = engine.getData()
console.debug("Data:", dataList[0])
}
}
...
@Custom type can not be recognized in QList. Anything wrong with my code and my understanding ?
Thank you all :D -
Seems related to: -https://snusmumriken.nokia.kunder.linpro.no/browse/QTBUG-20377-
EDIT: Correct link: https://bugreports.qt.nokia.com/browse/QTBUG-20377 - Volker