PDA

View Full Version : QtScript newFunction won't work



ihoss
24th November 2007, 17:04
I love the new QtScript module added to Qt 4.3, and I got the engine to do exactly what I wanted very quickly. But now I'm trying to add functions to the engine, specifically one that prints the arguments in a QTextEdit. I have looked at the documentation for QScriptEngine::newFunction (http://doc.trolltech.com/4.3/qscriptengine.html#newFunction), bit I just can't get it to work. Here is my code:

QScriptValue printString(QScriptContext *context, QScriptEngine *engine){
for(int i=0; i<context->argumentCount(); i++){
//outputText->append(context->argument(i).toString());
}
return context->callee();
}
void MainWindow::setupScripts(){
engine = new QScriptEngine();
QScriptValue fun = engine->newFunction(printString);
engine->globalObject().setProperty("print", fun, QScriptValue::ReadOnly | QScriptValue::Undeletable);
}

Whenever the code is compiled, I get the following error:

...:error: no matching function for call to `QScriptEngine::newFunction(<unknow type>)`

Anyone know why this might be?

jacek
26th November 2007, 00:22
Is printString() in the same .cpp file as MainWindow::setupScripts()?

ihoss
26th November 2007, 10:46
yup

Wow, yup is too short for me to post just that :p

jacek
26th November 2007, 16:50
yup
Is that the first error you get? Do you have QT += script in your .pro file?

ihoss
28th November 2007, 08:32
It is the first error, and I do have QT += script in the pro file. The thing is that the code compiles if I remove the newFunction line, and the compiled program works like intended.

jacek
28th November 2007, 12:43
The thing is that the code compiles if I remove the newFunction line, and the compiled program works like intended.
Is printString() defined before MainWindow::setupScripts()?

ihoss
28th November 2007, 12:56
I've uploaded the entire project so you can have a look at it. I have commented out the part that creates the new function. It's almost at the bottom of the cpp file.

jacek
28th November 2007, 13:28
The problem is that you have declared printString() method in MainWindow class and it takes precedence over printString() function. Just remove line #28 from mainwindow.h. Also you have to fix MainWindow::htmlize() -- it shouldn't return a reference.

ihoss
28th November 2007, 14:07
Thanks a lot, I had no idea why it wouldn't work :p

ihoss
30th November 2007, 17:46
Hokay, so I got it to work, but not the way I intended. What I want is for the print function to print something to the QTextEdit called outputText. Since the printString function is called as a static function, it can't point to outputText. I have tried lots of ways to get it to work, but all of them seem to throw some errors. Any idea how I can fix it?

jacek
2nd December 2007, 20:29
What I want is for the print function to print something to the QTextEdit called outputText.
You need a global variable or a singleton object to achieve this.

ihoss
2nd December 2007, 22:25
Hmm, I tried that, but I got an error with the .o compiled object file. It kept saying that it couldn't find the object that I made static. I don't have the code here, but what I did was to make a static variable which pointed to the QTextEdit I wanted to change. Then I initialized it in the constructor. I think this might have caused the error, since it wasn't 100% certain that the variable was initialized before it was retrieved in the static function called by the QtScript function. I'll post the code as soon as I get home if you don't already know what I messed up:p

ihoss
3rd December 2007, 01:11
Ok, so I worked around the problem by adding the instance of the current class, which only has one public slot, write, to the engine as an object called document. Then I added a script function called print that called document.write. It works :D This assumes that you only have one public slot. If you have lots of stuff that you want to hide, then create a new class which inherits from QObject and add that to the script engine. Here is the code:


engine = new QScriptEngine();
QScriptValue that = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeChildObjects
| QScriptEngine::ExcludeSuperClassMethods | QScriptEngine::ExcludeSuperClassProperties);
engine->globalObject().setProperty("document",that);
engine->evaluate("function print(str){return document.write(str);};");

jacek
3rd December 2007, 10:12
Then I added a script function called print that called document.write. It works :D This assumes that you only have one public slot. If you have lots of stuff that you want to hide, then create a new class which inherits from QObject and add that to the script engine.
This is a very good solution and quite similar to the singleton approach.