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
Forum Updated to NodeBB v4.3 + New Features

How to delete non QObject in QScript

Scheduled Pinned Locked Moved QML and Qt Quick
5 Posts 2 Posters 2.4k Views 1 Watching
  • 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