PDA

View Full Version : passing object to plugin



folibis
17th November 2011, 05:54
I have troubles with plugins in my application. In general this is only plugin loader.
I do it like this:


//main module
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMySettings * conf = new QMySettings("","");
QDir pluginsDir = QDir(qApp->applicationDirPath());
pluginsDir.cdUp();
pluginsDir.cd("plugins");
foreach (QString fileName, pluginsDir.entryList(QDir::Files))
{
QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = loader.instance();
if(plugin)
{
MyPlugin * iface = qobject_cast<MyPlugin *>(plugin);
if(iface)
{
iface->init(conf);
}
}
}
return a.exec();
}

In main module I initialize class for storing app configuration. This class I want to share with all of my plugins.

Conf::Conf(QObject *parent) :
QObject(parent)
{
}
//header
class Conf : public QObject
{
Q_OBJECT
public:
explicit Conf(QObject *parent = 0);
QString getValue(int i);
};

//cpp
QString Conf::getValue(int i)
{
return QString::number(i,16);
}

plugin interface


class MyPlugin
{
public:
~MyPlugin(){}
virtual void init(QObject * ptr) = 0;

};

Q_DECLARE_INTERFACE(MyPlugin,"com.trolltech.MyPlugin/1.0")

and finally my plugin implementation

//header
class LIB1SHARED_EXPORT Lib1 : public QObject,public MyPlugin {
Q_OBJECT
Q_INTERFACES(MyPlugin)
public:
Lib1();
void init(QObject * ptr);
};
//cpp
Lib1::Lib1()
{
}

void Lib1::init(QObject * ptr)
{
Conf * conf = reinterpret_cast<Conf *>(ptr);
qWarning(conf->getValue(1).toAscii()); // <<<<<<< here error
}

Q_EXPORT_PLUGIN2(lib1, Lib1)

While compiling I get strange error:

C:\source\PluginTest\lib1\lib1.cpp:11: error: undefined reference to `Conf::getValue(int)'
and what's interesting, using QSetting in place of My class works fine.

P.S. Sorry for my pure English

ChrisW67
17th November 2011, 08:18
Your plugin implementation will have to have access to the header declaring Conf in order to compile this code. On Linux that is probably sufficient. On Windows you might have to split Conf into a library that you can link the plugin against.

If you want a Conf* in the plugin why not define the interface as Conf* rather than QObject*?

folibis
17th November 2011, 12:54
the code compiles without problem, as you can see it is linker error;
and plugin implementation file include header declaring Conf.h

I can define
void Lib1::init(QObject * ptr)
as
void Lib1::init(Conf * ptr)

but it still say "undefined reference to `Conf::getValue(int)'"

d_stranz
17th November 2011, 22:22
You have an undefined reference because even though your plugin knows what a Conf class looks like (which means it can compile the code), it doesn't have any idea how to get the Conf instance to do anything, because you haven't linked in the object code that contains the Conf class implementation.

This is exactly what Chris was saying in his answer. Both the application and the plugin need to be linked against the Conf class object code if they need to use the objects. If all your plugin does is pass around pointers to Conf instances but never tries to call any Conf class methods, then you simply need the header file so it can be compiled. But it looks like you expect your plugins to be able to use the Conf pointers, so you will need all of then to link against the object code.

Either that, or put the Conf object code in a DLL and link all of your apps and plugins against that so you aren't duplicating code.