Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    How to delete non QObject in QScript

    QML and Qt Quick
    2
    5
    2097
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • L
      ludek.vodicka last edited by

      Hello there,

      I would like to ask how to define "onGarbage" method in Prototype object for non QObject class in QScript.

      I have following test class and correspond prototype class:

      @class CCalculator
      {
      int nNum1;
      int nNum2;

      public:
      CCalculator() : nNum1(0), nNum2(0) {}

      void SetNum1(int nNum) { nNum1 = nNum; }
      void SetNum2(int nNum) { nNum2 = nNum; }
      int GetNum1() { return nNum1;}
      int GetNum2() { return nNum2;}

      int GetSum() { return nNum1 + nNum2; }
      };

      //declare metatype
      Q_DECLARE_METATYPE(CCalculator*)

      //object prototype
      class CCalculatorPrototype : public QObject, public QScriptable
      {
      Q_OBJECT
      Q_PROPERTY(int nNum1 READ GetNum1 WRITE SetNum1 )
      Q_PROPERTY(int nNum2 READ GetNum2 WRITE SetNum2 )

      public:
      CCalculatorPrototype(QObject *parent = 0) : QObject(parent) {}
      ~CCalculatorPrototype() {}

      int GetNum1() const
      {
      CCalculator item = qscriptvalue_cast<CCalculator>(thisObject());
      return item ? item->GetNum1() : 0;
      }

      void SetNum1(int nNum)
      {
      CCalculator item = qscriptvalue_cast<CCalculator>(thisObject());
      if (item) item->SetNum1(nNum);
      }

      int GetNum2() const
      {
      CCalculator item = qscriptvalue_cast<CCalculator>(thisObject());
      return item ? item->GetNum2() : 0;
      }

      void SetNum2(int nNum)
      {
      CCalculator item = qscriptvalue_cast<CCalculator>(thisObject());
      if (item) item->SetNum2(nNum);
      }

      static QScriptValue constructCCalculator(QScriptContext * context, QScriptEngine *engine)
      {
      if (!context->isCalledAsConstructor())
      return context->throwError(QScriptContext::SyntaxError, "please use the 'new' operator");

      CCalculator * pCalculator = new CCalculator;
      return engine->newVariant(context->thisObject(), qVariantFromValue(pCalculator));
      }

      static QScriptValue destructorCCalculator(QScriptContext context, QScriptEngine )
      {
      CCalculator
      pCalculator = qscriptvalue_cast<CCalculator
      >(context->thisObject());
      if (!pCalculator)
      return context->throwError(QScriptContext::TypeError, "this object is not an CCalculator");

      delete pCalculator;
      return QScriptValue();
      }

      public slots:
      int GetSum() const
      {
      CCalculator item = qscriptvalue_cast<CCalculator>(thisObject());
      return item ? item->GetSum() : 0;
      }
      };@

      Now, I have following snippet which init QScriptEngine, register CCalculator class to it and try to use it:

      @ QScriptEngine engine;

      QScriptEngineDebugger debugger;
      debugger.attachTo(&engine);

      CCalculatorPrototype calcProto;
      QScriptValue calcProtoValue = engine.newQObject(&calcProto);
      calcProtoValue.setProperty("atEnd", engine.newFunction(CCalculatorPrototype::destructorCCalculator));
      engine.setDefaultPrototype(qMetaTypeId<CCalculator*>(), calcProtoValue);

      //constructor prototype
      QScriptValue calcCreator = engine.newFunction(CCalculatorPrototype::constructCCalculator, calcProtoValue);
      engine.globalObject().setProperty("CCalculator", calcCreator);

      //create calc
      engine.evaluate("calc = new CCalculator");
      engine.evaluate("calc.nNum1 = 10;");
      engine.evaluate("calc.nNum2 = 20;");

      //try calc
      QScriptValue valResult = engine.evaluate("calc.GetSum();");
      int nResult = valResult.toInt32();
      TEST_CHECK( nResult == 30 );@

      My problem is that object isn't automatically correctly released after QScriptEngine is destroyed. So I have memory leaks in this test case.

      I tried "atEnd" method referred in manual, but without success. How to correctly register destructor method in the prototype?

      Thank for any advice.

      Regards
      Ludek

      1 Reply Last reply Reply Quote 0
      • D
        dmcr last edited by

        Hi,
        may i ask you the reason why you are not using a QObject?

        dmcr

        1 Reply Last reply Reply Quote 0
        • L
          ludek.vodicka last edited by

          The reason is that I need to make existing objects available in QScript. Existing objects are from external libraries and I don't want to modify them.

          1 Reply Last reply Reply Quote 0
          • D
            dmcr last edited by

            So You can just 'embed' myObject in myQObject.
            You can then access to myObject with an accessor, managed by a QProperty for example,
            and then put the code to destruct myObject in the destructor of myQObject one.
            This should not take too long.

            dmcr

            1 Reply Last reply Reply Quote 0
            • L
              ludek.vodicka last edited by

              thanks for reply. I also found this solution.

              I'm curious what is the difference between embedding object to QObject and the way when I define construct method and METATYPE described here "Managing Non-QObject-based Objects":http://doc.qt.nokia.com/latest/scripting.html

              I also found solution for my problem with auto-deleting object. The solution is in passing QSharedPointer<> instead of C++ pointer to qVariantFromValue() method.

              Correct code look like this:

              @
              typedef QSharedPointer<CCalculator> PtrCalculator;
              Q_DECLARE_METATYPE(PtrCalculator)

              static QScriptValue constructCCalculator(QScriptContext * context, QScriptEngine *engine)
              {
              if (!context->isCalledAsConstructor())
              return context->throwError(QScriptContext::SyntaxError, "please use the 'new' operator");

              argument");

              PtrCalculator pCalculator(new CCalculator);
              return engine->newVariant(context->thisObject(), qVariantFromValue(pCalculator));
              }@

              Now memory is correctly released when QScriptEngine is destroyed.

              1 Reply Last reply Reply Quote 0
              • First post
                Last post