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