Providing Qt modules inside QtScript
-
I have been evaluating scripting languages to use for a project and had enough of all of them. Lately I've been going through the "QtScript documentation":http://qt-project.org/doc/qt-5/qtscript-index.html and eventually decided to give it a chance.
My intent is to provide plugins to my application via scripting. Plugins should be able to use some (all ?) of Qt's modules, mainly: Qt Widgets, Qt GUI, Qt Multimedia Widgets, Qt SQL. Objects created inside scripts should only be accessible and managed from inside the script [1]. Generally plugins are meant as an after-party addition (post application development); they should be independent from each other and, most importantly, independent (to some extent) of the C++ environment. By other means, each script is a Qt application entirely developed inside the scripting environment using the same modules as Qt in the C++ environment.Problem is that I haven't found documentation on how to access Qt's modules from the QtScript environment (except for manually writing wrappers for all the classes and providing them inside QtScript - which is a tremendous work prone to errors and bugs and any sort of issue you can immagine).
Can someone please tell me how to (easily) make available Qt modules inside QtScript? If this is not possible, or it's a tremendous work not worth doing, can you suggest any alternative scripting environment that I could use for my purpose?
Thank you in advance
[1] Any access from outside of the script (C++) might be done only if the proper script functions are exported to C++, but this is done by during application development only and is intended for mandatory scripts that should always run during the whole application execution.
-
QScriptEngine::newQObject most completely in the space moves to the script. but need care, and a good knowledge of javascript. especially the mechanism of prototypes.
Some specific types of data can not automatically be transferred to the script, their support will have to implement manually, but it is not too difficult.
Gui and widgets transferred to the scripts perfectly
@QUiLoader _uiLoader;
QWidget * qwWindow = _uiLoader.load(device, 0);
QScriptValue qsWindow = newQObject(qwWindow);
qsParent.setProperty(qwWindow->objectName(), QScriptValue(qsWindow));
QScriptValue qsWindowChild = newObject();
qsWindow.setProperty("widgets", QScriptValue(qsWindowChild));
foreach (QWidget *w, qwWindow->findChildren<QWidget *>()) {
QScriptValue qsWg = newQObject(w);
qsWindowChild.setProperty(w->objectName(), QScriptValue(qsWg));
}qwWindow->show();
@
-
This code transfer all widgets object to script. where you can manipulate controlls, signals and other.
try on their own to move objects that interest you through newQObject is how I understand the best mechanism for your application (but not only) for debugging and evaluation of scripts try module
it allows you to call a ready script debugger from the program. -
This code is perfectly valid when creating objects from C++ and then transferring them into the script. However I want to be able to create new objects directly from QtScript. For example I would like to be able to do this from QtScript:
@
// Creating a new QWidget with no parent (floating window)
var myWidget = new QWidget;
myWidget.setSize(300, 300);
myWidget.show();// Add a child QLabel to the previous QWidget
var myLabel = new QLabel(myWidget);
myLabel.setText("something");
myLabel.show();
@The same should be available for all classes of all mudules provided inside QtScript (in the example above, the Qt Widgets module should be provided).
I hope it's clearer now what I'm trying to achieve. -
Sorry, I not totally undestand this requirement:
bq. [1] Any access from outside of the script (C++) might be done only if the proper script functions are exported to C++, but this is done by during application development only and is intended for mandatory scripts that should always run during the whole application execution.bq.
if you need the autonomy of the code base is not correct to use independent language interpreters? and c ++ code (if you need it at all) to put in the library. you can use Java or Python (there is also a qt) -
I guess I have wrongly expressed myself. That note was about the possibility of adding objects from the C++ side to the QtScript environment which only stated that it would've been done at application development time only, so no plugin (script) shall create an object that is to be managed from C++.
After the application was developed, the application should be extensible through plugins - each plugin should be able to create new objects using qt's classes from the available modules such that it won't require C++ code to create, for example, a QWidget and expose it to the script; instead it will be the script itself to create the QWidget object and manage it.
The main problem is that QtScript seems not to have Qt's classes available for use within the script environment. So I am looking for a way to add qt's classes (from their respective modules) to the script environment to allow scripts to create QWidgets (and derivatives) and other Qt classes' objects.Does that make it clearer now?
-
bq. his code is perfectly valid when creating objects from C++ and then transferring them into the script. However I want to be able to create new objects directly from QtScript. For example I would like to be able to do this from QtScript:bq.
to create a new object in the script only need the ability to specify the class name as a string. the only solution I know of is the dynamic loading. In the code that I sent you boot just creates objects dynamically widgets. to create a new widget class without stopping the script via the QUiLoader, you must compile the class as a widget library and placed in a folder that looks loader. after can only create his team createWidget (module name)
if the QUiLoader transferred to the script without problems problem is already solved.
however for this case it is not necessary, such simple objects the script should be able to do myself, if not maybe you should put a flag in newQObject prototype or configure default prototype. -
Also for qobject you may use QPluginloader. a lower-level mechanism allows you to transfer the program qobject. and the lowest level there is a class loader qLibrary simple dynamic libraries. if the transfer is in the script of this class goes well there is a chance to make the script available to any system libraries.
-
Sorry mate, you're not getting it. I don't need these kind of plugins. The plugins I mean are created in JavaScript externally to the application. I don't need plugins to extend the C++ code base, I only need qt's classes (likw QWidget) to be available inside the QtScript environment, which is the JavaScript interpreter that runs the external plugins.
So thank you for your suggestions but they're not useful to me. -
Thank you too. Your question helped me a fresh look at the qscript .
but what I wrote about plugins refers specifically in the script. I meant that Qpluginloader can use the script to add classes qt, in the event of unforeseen circumstances. That is this is the only way to add classes c ++ script besides recompiling. -
Oh ok, that's a good way of adding functionalities to the compiled application. I'll consider using that.
But anyway, my problem persists. The QtScript environment only provides a JavaScript interpreter, with no Qt classes. Instead I would need to use Qt's classes inside the scripting environment just like I would do in C++.
Is there any way I can provide Qt's modules inside the QtScript environment ? -
I would still recommend you to take a more serious language. Python I think you should come. here is a list of available modules qt
"pyQt":http://pyqt.sourceforge.net/Docs/PyQt5/introduction.html#pyqt5-components
"pyside":http://www.pyside.org/ if you need LGPL License.from my own experience I can say that the prevalence of programming language is important. QScript not very common version of js so it is not as well tested / evaluated as a python or other, and support for it will be more difficult to obtain.
-
I also recommend you try the luaplus
"see this":http://gamedev.stackexchange.com/questions/8994/accessing-c-class-members-with-luaplus -
I found PyQt and PySide as well, 2 or 3 nights ago, and I was reading some pages about each. I was almost going for PySide, but then I noticed it only supports Qt 4.8 at most while my application is meant for Qt 5... Also I need LGPL so PyQt is a no-go as well since bindings for Qt5 are only available with a commercial license.
I'm not really into toLua++ and similar tools, I think that some manual work and proper testing is better than some auto-generated bindings. However, I seem to be left no other choice so I might give it a try... I have given up trying to find a way to bind Qt modules in the QtScript environment. It's a shame Qt devels didn't think of that themselves, I could see it as a very badass addition that would simply blow people's mind. -
Using Qt is a mandatory requirement?
If not, we can continue to communicate via email.
Otherwise, let's see what did not work with.
If you need support for a finite amount of classes qt + form creation through the script, it's a trivial task.
Just remember, the program on script like any script when a certain level of complexity turns into porridge. -
Yes, Qt is mandatory since these plugins should be able create widgets in a main window that I provide, other than being able to communicate over Internet and manage multimedia content.
I would need at least the core, widgets, multimedia and network modules. The XML and SQL modules woud be very handy so count them in as well. I dont need qml support, probably opengl neither...
It's obvious a script can't afford to run as fast as a compiled application but the usage of the plugins is limited to small widget-like apps. Also, i really love qt and the way it is/works, si why not using it inside the scripts as well :-) -
I partly understand the question. automatically transferred to the script only those parts of the qobject for which The generated meta-information. ie member of a class is declared as:
@public:
QMenu toolsMenu;@
will not be rescheduled. But if you declare it as:
@public:
Q_PROPERTY(QMenu toolsMenu MEMBER toolsMenu)
QMenu toolsMenu;@
then everything is OK. also need to be the type of object that was registered in the meta-object system
@Q_DECLARE_METATYPE(QMenu)@in result I mean two solutions:
1 change of attitude of the moc-compiler that he created the meta information for all parts of the object (this is unlikely, but it is tempting)
2 write simple wrappers for the basic kernel objects, like this:
@class QScriptDir : public QObject, public QDir
{
Q_OBJECT
public slots:
QStringList entryList(...){ return QDir::entryList(...); }
/* or more correctly */
public:
Q_INVOKABLE QStringList entryList(...){ return QDir::entryList(...); }
};@
incidentally for the object qdir is necessary in any case because it is not an qobject at all
I think in total will have to use the second option as the more correct, safe and portable. especially for a good lexer will not be difficult to write these wrappers automatically, with minor adjustments. approximately one week we will be enjoying the interface is fully implemented in the qscript. -
As it turns out the answer to the question is "there is no click-do way". I guess I've understood it long ago but I kind of just needed someone to tell me that.
Although it looks tempting to make the MOC do the work for you, I think it will just screw things up with way too much wrapper code and may possibly bring side-effects too.
The second solution is basically what they're suggesting when saying "write wrapper objects". I am considering to go trough it and see if it's worth it. But what if spend a week or more just doing this thing and then it may simply turn out not be worth it? I am studying some solutions to link a (any) scripting language to some C++ code that simply does what I need without the need for wrapper objects. Both solutions will have ups and downs, I just have to find out which is better.Thank you very much for the work you've done rst256. I will post again here as soon as I test some ideas going trough my mind right now, but I will need some time because I have to study for some university exams these days. Catch you later ;)