PDA

View Full Version : How to expose c++ plugins to Qml/QtCreator



dwalker0044
16th June 2011, 16:44
Hi everyone,

I'm developing an application using QML frontend with C++ backend. I have generated a plugin which was generated from C++ and I would now like to use this in Qml.

I believe I have imported the plugin correctly since when I run the program everything seems ok. So to clarify:

I Have a class called Box. I then have a class derived from QDeclarativeExtensionPlugin called BoxPlugin to expose the Box class to qml.



void BoxPlugin::registerTypes(const char *uri)
{
qmlRegisterType<Box>(uri, 1, 0, "Box");
}


I then build the project with the following .pro file:



TEMPLATE = lib
CONFIG += qt plugin
QT += declarative

DESTDIR = plugin
TARGET = boxPlugin

... headers and source files


Then in main.c I import the plugin:


QPluginLoader loader("C:/Qt/myExamples/CppQmlProject/Src/Components/BasicComponents/plugin/boxPlugin.dll");

QDeclarativeExtensionPlugin *plugin = qobject_cast<QDeclarativeExtensionPlugin *>(loader.instance());
if (plugin)
plugin->registerTypes("BasicComponents.Boxes");
else
qDebug() << "FAIL!";

view->setSource(QUrl("MainWindow.qml"));


I run the application and everything works fine. However, and what makes things very confusing, is that in MainWindow.qml, all the references to Box appear as errors, so:



import BasicComponents.Boxes 1.0

Box {
id: box
}


Would be underlined with a syntax error and the tooltip will pop up with, "unknown type".

Now I think I understand what is happening: the program works because it imports the plugin and the references to Box get resolved at runtime. But how can I make my plugin visible to QtCreator? I assume its possible since we use QtQuick and its modules are visible.

I feel there something important I'm missing because I'm assuming these plugins are for reusing modules from project to project and currently I don't see how this is done without the project having a local copy of the plugin?

I'll end this already long post here, I hope someone can help clarify this for me!

wysota
16th June 2011, 17:53
Search the docs for "qmldir"

dwalker0044
16th June 2011, 18:19
Hi wysota,

I have a qmldir file, its found in C:\Qt\CppQmlProject\Src\Components\BasicComponent and it looks like:

plugin boxPlugin /plugin

So it's pointing to the plugin dll which is found in the /plugin sub-directory.
I then have my QML_IMPORT_PATH in the projects Build Environment set to C:\Qt\CppQmlProject\Src\Components\

This I believes adds the import path as a location where the import statement looks. So When I:


import BasicComponents

this is essentially appending BasicComponents to the import path, so we have: C:\Qt\CppQmlProject\Src\Components\BasicComponents

which is where my qmldir file is. And should that resolve the references?

Thanks

wysota
16th June 2011, 18:34
Are you sure the directory name should start with a slash? In general I believe a correct qmldir file and the plugin together should resolve the problem in Creator.

dwalker0044
16th June 2011, 19:20
So I think the plugin itself is ok because I am able to access its properties. There's also no way I am by-passing the QPluginLoader section either because without it the application fails to load.

So there must be something wrong with either the qmldir file or perhaps its no even being read?

It must be sufficient since the qdeclarativemodules simply says I need, plugin <Name> [<Path>] which you can see from above I have that (I removed the slash, it didn't change anything).

Therefore QtCreator can't be reading it in the first place. So is what I've done correct? The plugin is not in the application directory. So I set the QML_IMPORT_PATH. By then attempting to import BasicComponents I'm then expecting QtCreator to look through all the import paths, appending the BasicComponents to the paths, then if there's a correct directory, then look for a qmldir file in that directory. Is that how the process works or have I gotten it wrong :confused:

wysota
16th June 2011, 19:39
Unfortunately I don't know such details. You'd have to look in Qt Creator source code to verify that. Also see if qmlviewer can detect your plugin using the qmldir file. If it works, Creator should detect it as well.

dwalker0044
17th June 2011, 11:07
Hi again,

So I tried to load a qml file which contains a reference to the plugin and it doesn't work. What's more annoying is that when I edit the file with QtCreator its happy with the type!

I've now copied the example found at http://qt.nokia.com/developer/learning/online/training/materials/qt-essentials-qt-quick-edition, downloaded the examples under the "Integrating QML with C++" heading and added the qml-cpp-integration/ex-extension-plugin to my project. I then build the project and try to load the standalone/ellipse9s.qml using the qmlviewer and again I get an error!


file:///C:/Qt/myExamples/CppQmlProject/Src/Components/Elipse/standalone/ellipse9s.qml:8:5: Ellipse is not a type
Ellipse {
^

Has anyone managed to get this example working?

I've tried opening the file directly (open the viewer, then file, navigate to ellipse9s, open ellipse9s) and also from the command line with a -I to add the import path:


qmlviewer -I qml-cpp-integration/ex-extension-plugin/standalone qml-cpp-integration/ex-extension-plugin/standalone/ellipse9s.qml

wysota
17th June 2011, 13:10
One thing to remember. Qt Creator is by default built against MSVC and Qt apps and probably your plugin as well is built against MinGW, so Creator might not be able to load it.

dwalker0044
21st June 2011, 09:39
I managed to get everything working by downloading the SDK and then following the steps mentioned here:http://developer.qt.nokia.com/forums/viewthread/5267
(when I opened qmldump.pro QtCreator instantly highlighted the missing headers)

Anyways I don't usually use the SDK and I tried to use the same fix for QtCreator, but it didn't appear to work - perhaps its the issue wysota mention,

Qt Creator is by default built against MSVC and Qt apps and probably your plugin as well is built against MinGW, so Creator might not be able to load it.
Haven't had time to look into this properly yet, but thanks for the suggestion!