June 17, 2011

Chuck Gao Chuck Gao
Lab Rat
329 posts

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:

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

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

  1. class CMyData: public QObject
  2. {
  3.     Q_OBJECT
  4.     Q_PROPERTY(int id READ id)
  5.  
  6. public:
  7.     explicit CMyData(QObject *parent = 0): QObject(parent) {}
  8.     CMyData(const CMyData& other): QObject() {}
  9.     ~CMyData() {
  10.         qDebug() << "haha";
  11.     }
  12.     int id() { return 11; }
  13. };
  14.  
  15. class CEngine : public QObject
  16. {
  17.     Q_OBJECT
  18. public:
  19.     explicit CEngine(QObject *parent = 0);
  20.  
  21.     Q_INVOKABLE QObjectList getDataList();
  22.     QObject* obj1;
  23.     QObject* obj2;
  24.     QObjectList* iList;
  25. };

// source file

  1. CEngine::CEngine(QObject *parent) :
  2.     QObject(parent)
  3. {
  4.     obj1 = new CMyData;
  5.     obj2 = new CMyData;
  6.  
  7.     iList = new QObjectList;
  8. }
  9.  
  10. QObjectList CEngine::getDataList()
  11. {
  12.     iList->append(obj1);
  13.     iList->append(obj2);
  14.  
  15.     return *iList;
  16. }

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 ?

 Signature 

Chuck

8 replies

June 20, 2011

aalpert aalpert
Lab Rat
41 posts

I believe this is the sort of confusion that QDeclarativeListProperty [doc.qt.nokia.com] 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.

June 20, 2011

Chuck Gao Chuck Gao
Lab Rat
329 posts

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

 Signature 

Chuck

June 20, 2011

aalpert aalpert
Lab Rat
41 posts

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.

June 20, 2011

Chuck Gao Chuck Gao
Lab Rat
329 posts

@aalpert: Clear. Thank you!

 Signature 

Chuck

June 20, 2011

Alex Liu Alex Liu
Lab Rat
17 posts
  • I don’t quite agree according to my experimentation. If I add a new function into above engine code like:
  1.  Q_INVOKABLE CMyData* getData() {
  2.         return new CMyData();
  3. }

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.

June 20, 2011

Chuck Gao Chuck Gao
Lab Rat
329 posts

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 . :-)

 Signature 

Chuck

June 20, 2011

Chuck Gao Chuck Gao
Lab Rat
329 posts

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

  1. QList<CMyData*> CEngine::getData()
  2. {
  3.     QList<CMyData*> myList;
  4.     CMyData *data = new CMyData();
  5.     QDeclarativeEngine::setObjectOwnership(data, QDeclarativeEngine::JavaScriptOwnership);
  6.     myList.append(data);
  7.  
  8.     return myList;
  9. }

  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication app(argc, argv);
  4.  
  5.     qmlRegisterType<CMyData>("CMyData", 1, 0, "CMyData");
  6.     qRegisterMetaType<CMyData>("CMyData");
  7.     CEngine *engine = new CEngine;
  8.  
  9.     QmlApplicationViewer viewer;
  10.     viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
  11.     viewer.rootContext()->setContextProperty("engine", engine);
  12.     viewer.setMainQmlFile(QLatin1String("qml/test/main.qml"));
  13.     viewer.showExpanded();
  14.  
  15.     return app.exec();
  16. }

// In qml file

  1. ...
  2. function getData()
  3. {
  4.   // Trigger garbage collection
  5.   for(var i=0; i<1000; i++)
  6.   {
  7.     var dataList = engine.getData()
  8.     console.debug("Data:", dataList[0])
  9.   }
  10. }
  11. ...

Custom type can not be recognized in QList. Anything wrong with my code and my understanding ?
Thank you all :D

 Signature 

Chuck

September 13, 2011

xizzhu xizzhu
Lab Rat
55 posts

Seems related to: https://snusmumriken.nokia.kunder.linpro.no/browse/QTBUG-20377

EDIT: Correct link: https://bugreports.qt.nokia.com/browse/QTBUG-20377 – Volker

 Signature 

My Blog: http://xzis.me/

 
  ‹‹ [Solved] Receiving signals from QML to C++      [Solved] Passing QAbstractItemModel subclasses to QML using a QObject property ››

You must log in to post a reply. Not a member yet? Register here!