Hello all,
I've been following the docs for developing a plugin for my Qt application, using the low-level approach, as well as the plug & paint example. For whatever reason, when I run my application, it detects the plugin files but cannot generate an instance from them. Here's what I've got (using a single plugin as an example, and the relevant sections of my application).
First, I'll start with my interface, input.h:
#ifndef INPUT_H
#define INPUT_H
# include <QObject>
class input
{
Q_OBJECT
public:
input() : allow(true){}
virtual ~input(){}
virtual const QString getName
()const = 0;
virtual const QString getDescription
()const = 0;
public slots:
virtual void setAllow(bool allow) = 0;
signals:
void menuUp();
void menuDown();
void menuLeft();
void menuRight();
protected:
bool allow;
};
Q_DECLARE_INTERFACE(input,
"com.warfaresdl.evilcpc.input/1.0.0")
#endif
#ifndef INPUT_H
#define INPUT_H
# include <QObject>
class QPoint;
class input
{
Q_OBJECT
public:
input() : allow(true){}
virtual ~input(){}
virtual const QString getName()const = 0;
virtual const QString getDescription()const = 0;
public slots:
virtual void setAllow(bool allow) = 0;
signals:
void menuUp();
void menuDown();
void menuLeft();
void menuRight();
void tap(const QPoint & p);
protected:
bool allow;
};
Q_DECLARE_INTERFACE(input,
"com.warfaresdl.evilcpc.input/1.0.0")
#endif
To copy to clipboard, switch view to plain text mode
And below, a sample input plugin, inputvoice.h:
#ifndef INPUTVOICE_H
#define INPUTVOICE_H
# include <input.h>
class inputVoice
: public input,
public QObject{
Q_OBJECT
Q_INTERFACES(input)
public:
virtual ~inputVoice();
virtual const QString getName
()const;
virtual const QString getDescription
()const;
public slots:
virtual void setAllow(const bool allow);
};
#endif
#ifndef INPUTVOICE_H
#define INPUTVOICE_H
# include <input.h>
class inputVoice : public input, public QObject
{
Q_OBJECT
Q_INTERFACES(input)
public:
inputVoice(QObject * p = 0);
virtual ~inputVoice();
virtual const QString getName()const;
virtual const QString getDescription()const;
public slots:
virtual void setAllow(const bool allow);
};
#endif
To copy to clipboard, switch view to plain text mode
... and its implementation, inputVoice.cpp:
#include "inputVoice.h"
#include <QtPlugin>
{
}
inputVoice::~inputVoice()
{
}
const QString inputVoice
::getName()const {
return tr("Voice");
}
const QString inputVoice
::getDescription()const {
return tr("Voice input plugin");
}
void inputVoice::setAllow(const bool a)
{
allow = a;
}
Q_EXPORT_PLUGIN2(inputVoice, inputVoice)
#include "inputVoice.h"
#include <QtPlugin>
inputVoice::inputVoice(QObject * p) : input(), QObject(p)
{
}
inputVoice::~inputVoice()
{
}
const QString inputVoice::getName()const
{
return tr("Voice");
}
const QString inputVoice::getDescription()const
{
return tr("Voice input plugin");
}
void inputVoice::setAllow(const bool a)
{
allow = a;
}
Q_EXPORT_PLUGIN2(inputVoice, inputVoice)
To copy to clipboard, switch view to plain text mode
The qmake .pro file for this plugin (voice):
TEMPLATE = lib
HEADERS = inputVoice.h
SOURCES = inputVoice.cpp
VERSION = 1.0.0
CONFIG = plugin debug_and_release qt
QT = core
INCLUDEPATH = ../interface
CONFIG(debug, debug|release) {
TARGET = inputVoice_debug
} else {
TARGET = inputVoice
}
TEMPLATE = lib
HEADERS = inputVoice.h
SOURCES = inputVoice.cpp
VERSION = 1.0.0
CONFIG = plugin debug_and_release qt
QT = core
INCLUDEPATH = ../interface
CONFIG(debug, debug|release) {
TARGET = inputVoice_debug
} else {
TARGET = inputVoice
}
To copy to clipboard, switch view to plain text mode
This generates a file, libinputVoice.so, which I sym-link to my application's project directory under a "plugins" sub-folder. My application uses the following qmake project file:
CONFIG = debug_and_release qt warn_on thread
QT = core
TEMPLATE = app
HEADERS =
SOURCES = main.cpp
INCLUDEPATH = ../plugins/menu/interface \
../plugins/menuItem/interface \
../plugins/input/interface
LIBS += -lmenu \
-lpanel \
-lncurses
CONFIG(debug, debug|release) {
TARGET = evilcpcconf-debug
} else {
TARGET = evilcpcconf
}
CONFIG = debug_and_release qt warn_on thread
QT = core
TEMPLATE = app
HEADERS =
SOURCES = main.cpp
INCLUDEPATH = ../plugins/menu/interface \
../plugins/menuItem/interface \
../plugins/input/interface
LIBS += -lmenu \
-lpanel \
-lncurses
CONFIG(debug, debug|release) {
TARGET = evilcpcconf-debug
} else {
TARGET = evilcpcconf
}
To copy to clipboard, switch view to plain text mode
... and in my application code, I use the following to load the plugin (stderr has been redirected to error.log via freopen):
unsigned int index;
//load plugins at this point...
#if defined(Q_OS_WIN)
if(pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
{
pluginsDir.cdUp();
}
#elif defined(Q_OS_MAC)
if(pluginsDir.dirName() == "MacOS")
{
pluginsDir.cdUp();
pluginsDir.cdUp();
pluginsDir.cdUp();
}
#endif
cerr << "Using plugin path: " << pluginsDir.absolutePath().toAscii().data() << endl;
pluginsDir.cd("plugins");
cerr << "Changed to: " << pluginsDir.absolutePath().toAscii().data() << endl;
foreach
(QString fileName, pluginsDir.
entryList(QDir::Files)) {
cerr << "Found a file: " << pluginsDir.absoluteFilePath(fileName).toAscii().data() << endl;
QObject * plugin
= loader.
instance();
if(!plugin)
{ // This is where each plugin is ending up
cerr << fileName.toAscii().data() << " is not a valid plugin..." << endl;
}
else
{
cerr << fileName.toAscii().data() << " is a valid plugin" << endl;
if(qobject_cast<input *>(plugin))
{
cerr << fileName.toAscii().data() << " is an input plugin" << endl;
input * i = qobject_cast<input *>(plugin);
lPluginFile << fileName;
lPluginName << i->getName();
lPluginDescription << i->getDescription();
}
}
}
if(!lPluginName.size())
{
return;
}
unsigned int index;
//load plugins at this point...
QStringList lPluginName;
QStringList lPluginDescription;
QStringList lPluginFile;
QDir pluginsDir = QDir(QCoreApplication::applicationDirPath());
#if defined(Q_OS_WIN)
if(pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
{
pluginsDir.cdUp();
}
#elif defined(Q_OS_MAC)
if(pluginsDir.dirName() == "MacOS")
{
pluginsDir.cdUp();
pluginsDir.cdUp();
pluginsDir.cdUp();
}
#endif
cerr << "Using plugin path: " << pluginsDir.absolutePath().toAscii().data() << endl;
pluginsDir.cd("plugins");
cerr << "Changed to: " << pluginsDir.absolutePath().toAscii().data() << endl;
foreach(QString fileName, pluginsDir.entryList(QDir::Files))
{
cerr << "Found a file: " << pluginsDir.absoluteFilePath(fileName).toAscii().data() << endl;
QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
QObject * plugin = loader.instance();
if(!plugin)
{ // This is where each plugin is ending up
cerr << fileName.toAscii().data() << " is not a valid plugin..." << endl;
}
else
{
cerr << fileName.toAscii().data() << " is a valid plugin" << endl;
if(qobject_cast<input *>(plugin))
{
cerr << fileName.toAscii().data() << " is an input plugin" << endl;
input * i = qobject_cast<input *>(plugin);
lPluginFile << fileName;
lPluginName << i->getName();
lPluginDescription << i->getDescription();
}
}
}
if(!lPluginName.size())
{
return;
}
To copy to clipboard, switch view to plain text mode
... and the cerr output:
Using plugin path: /home/rich/svn/evilcpc/trunk/evilcpcconf
Changed to: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libinputVoice.so
libinputVoice.so is not a valid plugin...
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libmenuAeon.so
libmenuAeon.so is not a valid plugin...
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libmenuBasic.so
libmenuBasic.so is not a valid plugin...
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libmenuItemGps.so
libmenuItemGps.so is not a valid plugin...
Using plugin path: /home/rich/svn/evilcpc/trunk/evilcpcconf
Changed to: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libinputVoice.so
libinputVoice.so is not a valid plugin...
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libmenuAeon.so
libmenuAeon.so is not a valid plugin...
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libmenuBasic.so
libmenuBasic.so is not a valid plugin...
Found a file: /home/rich/svn/evilcpc/trunk/evilcpcconf/plugins/libmenuItemGps.so
libmenuItemGps.so is not a valid plugin...
To copy to clipboard, switch view to plain text mode
What am I doing incorrectly in my plugin code?
Bookmarks