Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 4

Qt-interest Archive, December 2007
factory within plugins


Message 1 in thread

Qt!

Th plugin does not load.

It is desired to implement a factory within a plugin. So that it is possible
to create as many instances of the object embedded in the plugin as
required.

Maybe one cannot declare annother class (here BP) in the interface class for
the plugin ?!?
Because when I omit the BP class declaration and the getBP method in
BPInterface the plugin load without problems.

The problem is best described by the source code, no? Here it is:

Merry Christmas!!
Frank



bpinterface.h 
--------------------------------------------------------
class BP: public QObject
{
        Q_OBJECT
public:
        QString getName();
};
class BPInterface: public QObject
{

public:
        virtual ~BPInterface() {}

        virtual BP * getBP() = 0;
        virtual QString getName() = 0;

};
Q_DECLARE_INTERFACE(BPInterface,"Amatel.BPInterface/1.0")


main.cpp 
--------------------------------------------------------
#include "bpinterface.h"
void loadBP( QString fileName )
{
        qDebug() << "loadBP()" << fileName;
        QPluginLoader loader(fileName);
        QObject *plugin = loader.instance();
        if (plugin) {
                BPInterface * bp;
                bp = qobject_cast<BPInterface *>(plugin);
                if (bp) {
                        qDebug() << "plugin loaded";
                }
        }
        else
                qDebug() << "Mixer::loadBP() FAILED: " << fileName;
}
void loadBPdir( QString dirName )
{
        QDir pluginsDir(dirName);
        foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
                loadBP( pluginsDir.absoluteFilePath(fileName) );
        }
}
int main(int argc, char *argv[])
{
        QApplication app(argc, argv);
        loadBPdir("bp");
        return app.exec();
}

bp1.h 
--------------------------------------------------------
#include <bpinterface.h>
class BP1Plugin: public BPInterface
{
        Q_OBJECT
        Q_INTERFACES(BPInterface)
public:
        BP * getBP();
        QString getName();
};


bp1.cpp 
--------------------------------------------------------
#include "bp1.h"
QString BP1Plugin::getName()
{
        return QString("BP1");
}
BP * BP1Plugin::getBP()
{
        BP * bp = new BP();
        return bp;
}
QString BP::getName()
{
        return QString("BP 1");
}
Q_EXPORT_PLUGIN2(bp1, BP1Plugin)

bp1.pro 
--------------------------------------------------------
TEMPLATE      = lib
CONFIG       += plugin debug_and_release
INCLUDEPATH  += ../../app
HEADERS       = bp1.h
SOURCES       = bp1.cpp
TARGET        = bp1
DESTDIR       = ../../../bin/bp


--
 [ signature omitted ] 

Message 2 in thread

Hi again!!

I managed to load the plugin. The solution was to include "bpinterface.h" in
the HEADERS variable in "bp1.pro". 

But now the linker compains:

main.o: In function `main':
fac/src/app/main.cpp:68: undefined reference to `BP::getName()'
collect2: ld returned 1 exit status

The error ocurrs only if in main() a method of the factured class is called.

To reproduce this I attached a fac.tgz in this Mail.

> tar xvfz fac.tgz
> cd fac
> qmake -r
> make
> bin/fac

Any suggestions??

Frank


---------------------
files:
.
./bin
./bin/bp
./src
./src/bp
./src/bp/bp1
./src/bp/bp1/bp1.h
./src/bp/bp1/bp1.cpp
./src/bp/bp1/bp1.pro
./src/bp/bp.pro
./src/app
./src/app/main.cpp
./src/app/bpinterface.h
./src/app/app.pro
./src/src.pro
./fac.pro

Attachment:

Attachment: fac.tgz
Description: GNU Zip compressed data


Message 3 in thread

Hey, I didn't know that attachments are not allowed.

So I uploaded it to my account:

http://www-zeuthen.desy.de/~fwinter/fac.tgz

Just do a qmake -r and make.

To reproduce the linker error, uncomment line 68 in main.cpp:
        //qDebug() << bp->getName();

It is really clean code and uses an easy to understand structure. So If
someone managed to have a factory in a QPlugin, please tell me what's wrong
here.

Greetings,
Frank


--
 [ signature omitted ] 

Message 4 in thread

Frank wrote:
>To reproduce the linker error, uncomment line 68 in main.cpp:
>        //qDebug() << bp->getName();
>
>It is really clean code and uses an easy to understand structure. So If
>someone managed to have a factory in a QPlugin, please tell me what's
> wrong here.

The problem is that you're using a *plugin*.

As such, by definition, you load it at runtime. You don't link to it.

So you *cannot* use something defined in the plugin from the main 
application. You can only use the Qt plugin loading classes (and other 
similar API) to obtain symbols you want.
-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 5 in thread

Thiago,

does this mean, that it is in general impossible to realize a factory within
a plugin. "Factory" here means: I want to create more than one instance of
the loaded class (loaded as plugin).

Why do I want that? The loaded class represents a data reader, that is
queried multiple times for data simultanously. So I want to have different
instances of the data reader living in different threads to reply to these
request.

Greetings!
Frank


Thiago Macieira wrote:

> Frank wrote:
>>To reproduce the linker error, uncomment line 68 in main.cpp:
>>//qDebug() << bp->getName();
>>
>>It is really clean code and uses an easy to understand structure. So If
>>someone managed to have a factory in a QPlugin, please tell me what's
>> wrong here.
> 
> The problem is that you're using a *plugin*.
> 
> As such, by definition, you load it at runtime. You don't link to it.
> 
> So you *cannot* use something defined in the plugin from the main
> application. You can only use the Qt plugin loading classes (and other
> similar API) to obtain symbols you want.

--
 [ signature omitted ] 

Message 6 in thread

Frank,

Factories are how I do all my plugins.  I like to have the flexibility of creating multiple instances as well.

I know you have some of these done already, but here are the rules for Qt plugins:

The interface must not inherit QObject.

The interface must have no statics.

The interface must be declared with the Q_DECLARE_INTERFACE macro

The implementions of the interface must inherit multiply from QObject and the inteface

The impl must inherit QObject 1st.  Moc needs it 1st in the inheritance list

The impl must use the Q_OBJECT macro and the Q_INTERFACES macro

The impls must be delcared as plugins using the Q_EXPORT_PLUGIN2 macro

The headers in each .pro must be in the HEADERS line as they need to be run through moc.

Good luck,
Justin Noel
Sr. Consulting Engineer
ICS
http://ics.com

Sent from my BlackBerry® wireless device

-----Original Message-----
From: Frank <frank.t.winter@xxxxxxxxx>

Date: Tue, 25 Dec 2007 18:39:42 
To:qt-interest@xxxxxxxxxxxxx
Subject: Re: factory within plugins


Thiago,

does this mean, that it is in general impossible to realize a factory within
a plugin. "Factory" here means: I want to create more than one instance of
the loaded class (loaded as plugin).

Why do I want that? The loaded class represents a data reader, that is
queried multiple times for data simultanously. So I want to have different
instances of the data reader living in different threads to reply to these
request.

Greetings!
Frank


Thiago Macieira wrote:

> Frank wrote:
>>To reproduce the linker error, uncomment line 68 in main.cpp:
>>//qDebug() << bp->getName();
>>
>>It is really clean code and uses an easy to understand structure. So If
>>someone managed to have a factory in a QPlugin, please tell me what's
>> wrong here.
> 
> The problem is that you're using a *plugin*.
> 
> As such, by definition, you load it at runtime. You don't link to it.
> 
> So you *cannot* use something defined in the plugin from the main
> application. You can only use the Qt plugin loading classes (and other
> similar API) to obtain symbols you want.

--
 [ signature omitted ]