Reputation: 6478
I decided to switch my hobby project application (a dictionary lookup program) to a plugin architecture to enable all kinds of different dictionaries to be developed for other languages in the future. The application is developed in Visual C++ with Qt (5.0.2). I added this header to the application code to define the interface for the dictionary plugins:
// dict_plugin.h
#ifndef DICT_PLUGIN_H
#define DICT_PLUGIN_H
#include <QtPlugin>
class PluginInterface
{
public:
virtual ~PluginInterface() {}
virtual QString language() const = 0;
virtual class QWidget* ui() const = 0;
};
Q_DECLARE_INTERFACE(PluginInterface, "pl.ksmvision.winona.PluginInterface")
#endif // DICT_PLUGIN_H
Next, I created a new project from the "Qt library" template for the plugin itself (using the Qt Visual Studio add-in) which is used to make dll's. The main header file looks like this:
#ifndef JP_PLUGIN_H
#define JP_PLUGIN_H
// created by the template to define Q_DECL_EXPORT
// and _IMPORT macros but the plugin engine takes
// care of that (I think)
//#include "jp_plugin_global.h"
#include <QObject>
#include <QtPlugin>
#include <dict_plugin.h>
class JpPlugin : public QObject, public PluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "pl.ksmvision.winona.JpPlugin")
Q_INTERFACES(PluginInterface)
public:
JpPlugin();
virtual ~JpPlugin();
virtual QString language() const;
virtual QWidget* ui() const;
};
#endif // JP_PLUGIN_H
When I try to build this, I get an error from moc on the Q_INTERFACES line specifying the interfaces my plugin is supposed to be implementing:
3>------ Build started: Project: jp_plugin, Configuration: Debug Win32 ------
3> Moc'ing jp_plugin.h...
3>F:\moje\src\cpp\winona\build\jp_plugin\jp_plugin.h(15): error : Undefined interface
========== Build: 2 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
It looks like moc'ing takes place before the dict_plugin.h file is included, because when I introduce a typo to the include filename, it doesn't complain that the file doesn't exist, just terminates the build with that same error message about the interface being undefined.
What am I doing wrong? Thanks.
Upvotes: 3
Views: 4945
Reputation: 222
For those who venture down this path like I did. My issue was slightly different and had to do with namespaces. I was getting the exact same "undefined interface" error, but the path resolution had no effect for me.
I had something like the following:
namespace foo {
class Interface
{
// ...
};
} // namespace foo
Q_DECLARE_INTERFACE(foo::Interface, "my.interface/1.0")
namespace foo {
class Derived : public QObject, public Interface
{
Q_OBJECT
Q_INTERFACES(Interface)
};
}
namespace foo {
class Derived : public QObject, public Interface
{
Q_OBJECT
Q_INTERFACES(foo::Interface) //!< Notice foo:: is still provided
};
}
From the documentation:
If you want to use Q_DECLARE_INTERFACE with interface classes declared in a namespace then you have to make sure the Q_DECLARE_INTERFACE is not inside a namespace though.
But what they don't mention is that the Q_INTERFACES()
, even when inside of that namespace by scope, still requires the namespace be provided as though it were global.
Upvotes: 0
Reputation: 6478
The reason moc failed was because the interface declaration was unavailable. The #include directive failed because the file could not be found. Apparently, moc can process #include directives by itself, but doesn't (by default?) print an error message or halt processing if the file to be included can't be found.
The reason the header file with the interface declaration could not be found is that the custom build settings which cause moc to be invoked that are generated by the Qt VS add-in don't inherit the project's include path. I managed to add the required path manualy to moc's command line by entering the property pages of the plugin's header file, browsing to Custom Build Tool->General->Command Line and adding an extra "-I..." include option at the end. After that, moc processed the header and the build was successfull.
Upvotes: 6