Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to delete non QObject in QScript

How to delete non QObject in QScript

Scheduled Pinned Locked Moved QML and Qt Quick
5 Posts 2 Posters 2.3k Views
  • 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 Offline
    L Offline
    ludek.vodicka
    wrote on last edited by
    #1

    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
    0
    • D Offline
      D Offline
      dmcr
      wrote on last edited by
      #2

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

      dmcr

      1 Reply Last reply
      0
      • L Offline
        L Offline
        ludek.vodicka
        wrote on last edited by
        #3

        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
        0
        • D Offline
          D Offline
          dmcr
          wrote on last edited by
          #4

          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
          0
          • L Offline
            L Offline
            ludek.vodicka
            wrote on last edited by
            #5

            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
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved