PDA

View Full Version : Qt plugin: access application classes from the plugin?



abey
29th October 2009, 20:11
Hello all,

Please consider the following mock-up of how my application works:


class DataSource
{
public:
QVariant dataForKey(const QString &key);
};


class BaseWidget : public QWidget
{
Q_OBJECT
public:
BaseWidget(QWidget* parent);
void setDataSource(DataSource* ds) { this->ds = ds; }
virtual void draw(QPainter* painter) = 0;
protected:
DataSource* ds;
};

class SomeWidget : public BaseWidget
{
public:
virtual void draw(QPainter* painter)
{
// do some custom drawing using ds->dataForKey()
// with specific "key" parameter
}
};


My application has a repertoire of subclasses of BaseWidget that I would like to dynamically extend through plugins. Qt's documentation (http://doc.trolltech.com/4.5/plugins-howto.html) is quite clear on the basics, but covers only the case where the plugin can be implemented exclusively with pure Qt facilities. In this case, I would like the plug-in to be able to access my custom facilities, i.e. the DataSource mechanism in the mock-up above.

I'm not sure how to proceed toward the implementation of such a setup. How can I provide the plugins with access to facilities sitting in the main application? Should I put these facilities in a separate dynamic library against which both the application and the plugins will be linked? Or is there a potentially simpler way to achieve this?

Thanks in advance for your help,
Antoine

be-noix
13th November 2009, 19:32
Hi!

I had exactly the same question...

Did you find a good solution?

Or do people have some idea?
(for example, can we declare an interface in the main application ?)

Thanks a lot
Cheers,
Benoit

QPlace
13th November 2009, 21:40
You are exporting SomeWidget class in your plugin to the application, aren't you?

If yes, then it is not that "application has a repertoire of subclasses of BaseWidget ", but a plugin has them.

In the mockup that you provided it looks like that any class in your plugin that implements BaseWidget interface will have an access to DataSource. But, as far as I know, only one class can be exported from the plugin, except multiple inheritance construct of type (then you can cast returned "instance" it to the base types)

class ExportedWidget: public SomeWidget1, public SomeWidget2, public BaseWidget
{
..
Q_INTERFACES(BaseWidget)
..
}

abey
15th November 2009, 15:11
You are exporting SomeWidget class in your plugin to the application, aren't you?

If yes, then it is not that "application has a repertoire of subclasses of BaseWidget ", but a plugin has them.

Agreed.


In the mockup that you provided it looks like that any class in your plugin that implements BaseWidget interface will have an access to DataSource. But, as far as I know, only one class can be exported from the plugin, except multiple inheritance construct of type (then you can cast returned "instance" it to the base types)

I'm not sure I understand your point. I agree that my mockup lacks the Qt-isms specific to plug-ins. And yes, I don't expect plug-in to export more than a single class. The question was about the use in the plugin of facilities sitting in the application.

be-noix
15th November 2009, 22:09
By reading a lot of posts on the forum it seems that the best way is to use a shared library for the functions used by both the plugins and the application.

Ben

abey
16th November 2009, 08:19
By reading a lot of posts on the forum it seems that the best way is to use a shared library for the functions used by both the plugins and the application.

Ben

I see. Out of curiosity, can you think of another way?

masterbraind
5th August 2011, 14:45
Function defined in your interface:


virtual void Initialize(int *AHostClass) = 0;


When you call it after load the plugin you should send the class pointer like this (this for the caller class, or any other class pointer):


PluginLoader_Class_Object->Initialize(reinterpret_cast<int*>(this));


Inside of the plugin you shoul convert this int to a class again creating a class pointer and asignating this value to it.


void Initialize(int *AHostClass)
{
TCLASS *HostClassInsidePlugin;
HostClassInsidePlugin = reinterpret_cast<TCLASS *>(AHostClass);
HostClassInsidePlugin->... any member of the class passed.
...
}

Remember thath you shoud have the same exactli header .h from the host application insite of you plugin proyect.

idle17
11th April 2013, 10:55
It is possible to call back from plugin into application using pointer to function:



// plugin
void MyPlugin::someFunctionInPlugin(int (*functionInApp)())
{
int result = (*functionInApp)();
}

// application code
int someFunctionInApp()
{
...
}
void someOtherFunctionInApp()
{
plugin->someFunctionInPlugin(&someFunctionInApp);
}


Member function of class defined in application might be called from plugin if this function is virtual (at least it may compile without errors), or when it is passed via pointer to member function:



// plugin
void MyPlugin::someFunctionInPlugin(ClassInApp *obj, void (*ClassInApp::Fun)())
{
obj->virtualFunction();
((*obj).*(Fun))();
}

// application
class ClassInApp
{
virtual void virtualFunction();
void someMemberFunction();
};

void someFunctionInApp()
{
ClassInApp obj;
plugin->someFunctionInPlugin(&obj, &ClassInApp::someMemberFunction);
}