PDA

View Full Version : QtScript: default constructor question



QPlace
22nd October 2009, 18:24
Studying QtScript examples and using my own code (see my previous post regarding QtScript (http://www.qtcentre.org/forum/f-qt-programming-2/t-qtscript-evaluation-question-24985.html) ) I can't quite understand how QtScript instantiate C++ classes where constructor has arguments.

Tracing the code (shown below) I can see that default constructor with no arguments get called, then my factory code get called and correct test(int) is called with agrument (10, in my case), but at the end of it my script receives an instance constructed with prototype where default constructor is invoked (_i == 0) . So, when following script is evaluated, returned value is 1 and not 11 as I expect.

Any comments, suggestions are very much appreciated.

//Script that is evaluated
var t = new test(10)
t.val + 1


// part of the code that evaluates script
QString script = scriptText; // above script
QScriptEngine interpreter;
test::registerWithScript("test", interpreter);
QScriptValue result = interpreter.evaluate(script);


// support class to help with default constructor and registering
template <typename T> class Scriptable
{
public:
Scriptable()
{
}


static void registerWithScript(const char* scriptObjName, QScriptEngine& scriptengine)
{
T* t = new T();
QScriptValue obj = scriptengine.newQObject(t, QScriptEngine::ScriptOwnership);
scriptengine.setDefaultPrototype(qMetaTypeId<T>(),obj);
QScriptValue objCtor = scriptengine.newFunction(objectConst, obj);
scriptengine.globalObject().setProperty(scriptObjN ame, objCtor);
}

private:
static QScriptValue objectConst (QScriptContext* context, QScriptEngine* scriptengine)
{
boost::scoped_ptr<T> t(T::factory (context));
return scriptengine->toScriptValue(*t);
}
};


//test class; to study QtScript
class test : public QObject, public QScriptable, public Scriptable<test>
{
Q_OBJECT
Q_PROPERTY(int val READ val WRITE set)
public:
test (int i = 0) : _i(i)
{
}
test (const test& another) : _i(another._i)
{
int i = _i;
}
virtual ~test ()
{
int i = _i;
}

test& operator = (const test& another)
{
_i = another._i;
return *this;
}
void set(int i)
{
_i = i;
}
int val()
{
return _i;
}

static test* factory (QScriptContext* context)
{
if (context->argumentCount() == 0)
return new test();
else
{
int i = context->argument(0).toInt32();
return new test(i);
}
}
private:
int _i;
};

Q_DECLARE_METATYPE(test)
Q_DECLARE_METATYPE(test*)

QPlace
22nd October 2009, 20:36
I found a solution that works. Actually, by saying "found" in this specific case I meant that I found a discrepancy between "Foundations_of_qt_development" and Qt documentation. Qt wins.


//Following are the changes in my support class. It might help someone hitting similar issue. Commented lines are "old version".
template <typename T> class Scriptable
{
public:
Scriptable()
{
}


static void registerWithScript(const char* scriptObjName, QScriptEngine& scriptengine)
{
T* t = new T();
QScriptValue obj = scriptengine.newQObject(t, QScriptEngine::ScriptOwnership);
scriptengine.setDefaultPrototype(qMetaTypeId<T>(),obj);

// QScriptValue objCtor = scriptengine.newFunction(objectConst, obj);
// scriptengine.globalObject().setProperty(scriptObjN ame, objCtor);


QScriptValue ctor = scriptengine.newFunction(objectConst);
QScriptValue metaObject = scriptengine.newQMetaObject(&QObject::staticMetaObject, ctor);
scriptengine.globalObject().setProperty(scriptObjN ame, metaObject);
}

private:
static QScriptValue objectConst (QScriptContext* context, QScriptEngine* scriptengine)
{
// boost::scoped_ptr<T> t(T::factory (context));
// return scriptengine->toScriptValue(*t);
T* t = T::factory (context);
return scriptengine->newQObject(t, QScriptEngine::ScriptOwnership);
}
};