PDA

View Full Version : QtScript: accessing methods of QObject* subclass from script



profoX
11th April 2012, 01:11
I am very new to QtScript and I have used QScriptEngine::evaluate() to evaluate this script:



function render(node) {
var stream = node.getStream();
print("typeof stream "+typeof stream + "," + stream);
var test = stream.test();
}


Now, I have used Q_DECLARE_METATYPE(Stream*)
and node.getStream() returns Stream*

In the script the output is as follows:


typeof stream object,QVariant(Stream*)

Stream has a public slot with testmethod() returning an int:



public slots:
int testmethod() {return 8;}

But then I get the following TypeError in the script when I try to access the testmethod() method of Stream

TypeError: Result of expression 'stream.testmethod' [undefined] is not a function.

I am obviously not doing this right? Can someone help me in the right direction to make this work?

Many thanks.

[Zero]
5th July 2012, 01:09
Bump, same problem.

wysota
5th July 2012, 01:27
The object needs to be exposed as QObject and not QVariant.

[Zero]
5th July 2012, 01:58
Ok, mine is not exactly the same problem.

I had exposed a instance of a class that inherits QObject, ClsUserManager:


engine.globalObject().setProperty("UserManager",engine.newQObject(UserManager));

UserManager has this public slot:

OtherCustomClass* getUser(QString id);

OtherCustomClass has a slot:

void setProperty(QString p)

I tried to call de slot from my script:

UserManager.getUser(id).setProperty(p);

I get:

Debug: "TypeError: cannot call getUser(): unknown return type `OtherCustomClass*' (register the type with qScriptRegisterMetaType())"

The problem is that I can't call qScriptRegisterMetaType() from OtherCustomClass, it gets "QScriptEngine * engine" as first param, and I created some instances of QScriptEngine (by demmand) dinamically.

Regards

wysota
5th July 2012, 09:58
Does "OtherCustomClass" inherit QObject?

[Zero]
5th July 2012, 18:13
Yes, all classes I use in the project inherit QObject.

wysota
5th July 2012, 22:02
Does it have a Q_OBJECT macro?

[Zero]
5th July 2012, 22:07
Yes, I can call their slots from C++ code without any problem. I could try to reproduce it on a minimal compilable project if you need it.

wysota
5th July 2012, 23:22
Ok, got it...

The problem is that you need to teach your script engine to convert your objects to script values.

Here is the relevant code:


Q_DECLARE_METATYPE(OtherCustomClass*)

QScriptValue toScriptValue(QScriptEngine *e, OtherCustomClass* const &o) {
return e->newQObject(o);
}

void fromScriptValue(const QScriptValue &val, OtherCustomClass* &o) {
o = qobject_cast<OtherCustomClass*>(val.toQObject());
}

qScriptRegisterMetaType<OtherCustomClass*>(engine, fromScriptValue, toScriptValue);

Or more general:


template <typename Tp>
QScriptValue qScriptValueFromQObject(QScriptEngine *engine, Tp const
&qobject)
{
return engine->newQObject(qobject);
}

template <typename Tp>
void qScriptValueToQObject(const QScriptValue &value, Tp &qobject)
{
qobject = qobject_cast<Tp>(value.toQObject());
}

template <typename Tp>
int qScriptRegisterQObjectMetaType(
QScriptEngine *engine,
const QScriptValue &prototype = QScriptValue()
#ifndef qdoc
, Tp * /* dummy */ = 0
#endif
)
{
return qScriptRegisterMetaType<Tp>(engine, qScriptValueFromQObject, qScriptValueToQObject, prototype);
}

qScriptRegisterQObjectMetaType<OtherCustomClass*>(engine);

The last snippet is not my invention, borrowed it from here: http://lists.trolltech.com/qt-interest/2007-12/thread00158-0.html

[Zero]
5th July 2012, 23:48
Solved, Thank you very much! :D