Results 1 to 12 of 12

Thread: Plugin interface with slots and signals

  1. #1
    Join Date
    Nov 2011
    Posts
    79
    Thanks
    5
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Plugin interface with slots and signals

    Now I work on application with plugins.
    So I have one interface and lots of plugins based on it:

    Qt Code:
    1. class PluginWidgetInterface
    2. {
    3. public:
    4. virtual ~PluginWidgetInterface() {}
    5. virtual QWidget * GetWidget() = 0;
    6. //---------------------------- SIGNALS ---------------------------
    7. virtual void MessageSend() = 0;
    8. };
    9.  
    10. #define PluginWidgetInterface_iid "myplugins.PluginWidgetInterface"
    11. Q_DECLARE_INTERFACE(PluginWidgetInterface, PluginWidgetInterface_iid)
    To copy to clipboard, switch view to plain text mode 

    and plugin implementation:
    Qt Code:
    1. #include "plugininterface.h"
    2.  
    3. class Plugin1 : public QObject,PluginWidgetInterface
    4. {
    5. Q_OBJECT
    6. Q_PLUGIN_METADATA(IID "myplugins.Plugin1")
    7. Q_INTERFACES(PluginWidgetInterface)
    8. public:
    9. ~Plugin1() {}
    10. QWidget * GetWidget();
    11. //---------------------------- SIGNALS ---------------------------
    12. void MessageSend();
    13. };
    To copy to clipboard, switch view to plain text mode 

    but at this point i have troubles with connect(). Because the Interface class not derived from QObject I cant use it with connect();
    If i cast it to QObject i get 0x0.

    Qt Code:
    1. QPluginLoader loader("plugin.dll");
    2. PluginWidgetInterface * plugin = qobject_cast<PluginWidgetInterface *>(loader.instance());
    3. QWidget * widget = plugin->GetWidget();
    4. QObject * o = dynamic_cast<QObject *>(plugin); // here o = NULL
    5. connect(o,SIGNAL(MessageSend),this,SLOT(MessageReceived));
    To copy to clipboard, switch view to plain text mode 

    I would like to do it in new style
    Qt Code:
    1. connect(o,&PluginWidgetInterface::MessageSend,this,&MainWindow::MessageReceived);
    To copy to clipboard, switch view to plain text mode 
    but i got error:
    no matching function for call to 'MainWindow::connect(QObject*&, void (PluginWidgetInterface::*)(), MainWindow* const, void (MainWindow::*)())


    So what is right way to define interface with signals to connect inheritance to slots?
    Last edited by folibis; 9th September 2013 at 11:28.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Some things:
    is the private inheritance of the interface class by accident?
    you plugin implementation is missing the signals: section.
    does GetWidget() return a valid widget pointer?
    if yes, why don't you use that in the connect?

    Cheers,
    _

  3. #3
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Since you are requiring that all of the plugins have a MessageSend signal, just derived your initial plugin interface from QObject and include the signal there
    Qt Code:
    1. class PluginWidgetInterface : public QObject
    2. {
    3. Q_OBJECT
    4. public:
    5. virtual ~PluginWidgetInterface() {}
    6. virtual QWidget * GetWidget() = 0;
    7. signals:
    8. void MessageSend();
    9. };
    To copy to clipboard, switch view to plain text mode 
    You will still need to use Q_OBJECT in your derived classes
    Qt Code:
    1. class Plugin1 : public PluginWidgetInterface
    2. {
    3. Q_OBJECT
    4. Q_PLUGIN_METADATA(IID "myplugins.Plugin1")
    5. Q_INTERFACES(PluginWidgetInterface)
    6. public:
    7. ~Plugin1() {}
    8. QWidget * GetWidget();
    9. };
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Nov 2011
    Posts
    79
    Thanks
    5
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Quote Originally Posted by mcarter View Post
    Since you are requiring that all of the plugins have a MessageSend signal, just derived your initial plugin interface from QObject and include the signal there
    Ok, I derived interface class from QObject. Now, when I compile plugin dll I get lots of errors like:
    error: undefined reference to `PluginWidgetInterface::qt_metacast(char const*)

    I guess I have to put interface class in different library and link in statically with all plugins dlls but it looks too complicated
    Last edited by folibis; 9th September 2013 at 22:50.

  5. #5
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    As long as you are not linking against a statically built Qt then everythign should work fine.
    The following code builds plugin lib in linux, and I think should build proper dll in windows

    Qt Code:
    1. #ifndef _PLUGIN_WIDGET_INTERFACE_H_
    2. #define _PLUGIN_WIDGET_INTERFACE_H_
    3.  
    4. #include <QtPlugin>
    5. #include <QObject>
    6.  
    7. class PluginWidgetInterface : public QObject
    8. {
    9. Q_OBJECT
    10. public:
    11. virtual ~PluginWidgetInterface() {}
    12. virtual QWidget * GetWidget() = 0;
    13. signals:
    14. void MessageSend();
    15. };
    16.  
    17. #define PluginWidgetInterface_iid "myplugins.PluginWidgetInterface"
    18. Q_DECLARE_INTERFACE(PluginWidgetInterface, PluginWidgetInterface_iid)
    19.  
    20. #endif
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. #ifndef _PLUGIN1_H_
    2. #define _PLUGIN1_H_
    3.  
    4. #include "plugininterface.h"
    5.  
    6. class Plugin1 : public PluginWidgetInterface
    7. {
    8. Q_OBJECT
    9. //Q_PLUGIN_METADATA(IID "myplugins.Plugin1")
    10. Q_INTERFACES(PluginWidgetInterface)
    11. public:
    12. ~Plugin1() {}
    13. QWidget * GetWidget();
    14. };
    15.  
    16. #endif
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. #include "plugin1.h"
    2.  
    3. QWidget * Plugin1::GetWidget()
    4. {
    5. return 0;
    6. }
    7.  
    8. Q_EXPORT_PLUGIN2(plugin1, Plugin1);
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. TEMPLATE = lib
    2. TARGET =
    3. DEPENDPATH += .
    4. INCLUDEPATH += .
    5.  
    6. # Input
    7. HEADERS += plugin1.h plugininterface.h
    8. SOURCES += plugin1.cpp
    To copy to clipboard, switch view to plain text mode 

    Can then be used with
    Qt Code:
    1. QPluginLoader loader( qstrLibFilename );
    2. PluginWidgetInterface * plugin = qobject_cast<PluginWidgetInterface *>(loader.instance());
    3. QWidget * widget = plugin->GetWidget();
    4. connect(plugin,SIGNAL(MessageSend()),this,SLOT(MessageReceived()));
    To copy to clipboard, switch view to plain text mode 

  6. The following user says thank you to mcarter for this useful post:

    folibis (10th September 2013)

  7. #6
    Join Date
    Nov 2011
    Posts
    79
    Thanks
    5
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Yes, as I see this code have to work fine. But if you have 20 plugins you duplicate code of PluginWidgetInterface in all of plugins
    Just because of this problem I decided do do virtual base interface - in this case you need only include "plugininterface.h" into implementation.
    If you derive base interface from QObject you have to organize it as dufferent lib or duplicate code in all of plugins. Correct me if I'am wrong.


    Added after 36 minutes:


    I guess I've found a solution.
    The base interfase not derived from QObject but plugins do it, exactly as in my first post.
    in main app I do that:
    Qt Code:
    1. QPluginLoader loader("plugin.dll");
    2. QObject * obj = loader.instance();PluginWidgetInterface * plugin = qobject_cast<PluginWidgetInterface *>(obj);
    3. QWidget * widget = plugin->GetWidget();
    4. connect(obj,SIGNAL(MessageSend),this,SLOT(MessageReceived));
    To copy to clipboard, switch view to plain text mode 

    Not nice solution but at least it works.

    "new style" of connect still not works
    Qt Code:
    1. connect(obj,&PluginWidgetInterface::MessageSend,this,&MainWindow::MessageReceived);
    To copy to clipboard, switch view to plain text mode 
    Last edited by folibis; 10th September 2013 at 05:08.

  8. #7
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Quote Originally Posted by folibis View Post
    Not nice solution but at least it works.
    Looks nice to me.
    You get the plugin instance, you connect to its signal and you're done.

    Cheers,
    _

  9. #8
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Quote Originally Posted by folibis
    Yes, as I see this code have to work fine. But if you have 20 plugins you duplicate code of PluginWidgetInterface in all of plugins
    Just because of this problem I decided do do virtual base interface - in this case you need only include "plugininterface.h" into implementation.
    If you derive base interface from QObject you have to organize it as dufferent lib or duplicate code in all of plugins. Correct me if I'am wrong.
    What code needs to be duplicated from PluginWidgetInterface with the implementation that I showed? As with any derived class, you only need to implement any abstract methods and any code for the specific plugin. There is no extra qobject code that needs to be implemented. The code that uses the plugin still just needs the 'plugininterface.h'.

    In your example, GetWidget is still abstract and needs to be implemented in all plugins. If you abstract MessageSend, then you will need that signal defined in all plugins, duplicating code there, and then the only way to access it will be thru the loader.instance() object since PluginWidgetInterface will not have that object signal definition/implementation, as you saw with connect(obj,...) and not connect(plugin,...).

    What does not work with the new style of connect? Not sure you can use &PluginWidgetInterface::MessageSend because that is not defined an actual signal in plugininterface.h.

    I would be interested to see your implementation.

  10. #9
    Join Date
    Nov 2011
    Posts
    79
    Thanks
    5
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    I mean if the base interface derived from QObject so it must be a "real object", not just declaration in *.h file. So you must link all of plugins with this object
    At least when I've tried your soluton i got lots of linker errors while plugin compiling like:
    error: undefined reference to `PluginWidgetInterface::qt_metacast(char const*)'

    Quote Originally Posted by anda_skoa View Post
    Looks nice to me.
    You get the plugin instance, you connect to its signal and you're done.
    _
    Yes, it works, but i would like to use "new" connect. As I understand it works a bit faster.
    This does not work and I don't like the fact that I can't do what I want

  11. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Plugin interface with slots and signals

    Quote Originally Posted by folibis View Post
    As I understand it works a bit faster.
    How did you measure it? How much impact performance of a connect() call has for efficiency of your code? Is it a bottleneck of your application? If someone pays you to do this, did you compare the amount of money he spent on you thinking about the problem with the possible benefit the users are going to have with a presumably faster connect() execution?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #11
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Quote Originally Posted by folibis View Post
    I mean if the base interface derived from QObject so it must be a "real object", not just declaration in *.h file. So you must link all of plugins with this object. At least when I've tried your soluton i got lots of linker errors while plugin compiling like:
    error: undefined reference to `PluginWidgetInterface::qt_metacast(char const*)'
    You never create an instance of PluginWidgetInterface, but plugininterface.h must be included in HEADERS for all plugins and the main app, and you need to make sure that plugininterface.h is moc'd. I was able to verify this all works in windows, so it sounds like it might be your build process. Are you using mingw in windows or using the Qt addin for visual studio? What does your .pro file look like?

  13. #12
    Join Date
    Nov 2011
    Posts
    79
    Thanks
    5
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Plugin interface with slots and signals

    Ok, I've created simple test project. That is exactly what I need, mainly connect() in main.cpp
    There are 2 subprojects - Main and Plugin/ I was not able to compile it since base interfase derived from QObject.
    Attached Files Attached Files

Similar Threads

  1. Replies: 2
    Last Post: 18th April 2013, 12:15
  2. Problem with plugin signals/slots
    By DiamonDogX in forum Qt Programming
    Replies: 8
    Last Post: 5th June 2009, 16:01
  3. Signals and Slots over interface
    By SnarlCat in forum Qt Programming
    Replies: 3
    Last Post: 1st May 2009, 17:57
  4. Plugin-signals-slots problem
    By Misenko in forum Qt Programming
    Replies: 8
    Last Post: 23rd September 2008, 20:53
  5. Plugin interfaces, signals and slots
    By QPlace in forum Qt Programming
    Replies: 8
    Last Post: 9th August 2007, 21:19

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.