How to delete non QObject in QScript



  • 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



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



  • 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.



  • 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.



  • 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.