Results 1 to 13 of 13

Thread: Plugin implementation question

  1. #1
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Plugin implementation question

    Hi

    I am stuck while trying to implement an plugin-aware application. Mainly because I'm not sure it what I want to do is possible: I have a MDI area in my main window and I want to populate it with widgets obtained through a plugin interface. I've studied the plugin examples in the Qt documentation as well as the plugin interface described in "C++ GUI Programming with Qt" and they all differ from what I need because the plugins all return a object known to Qt, for example a QPixmap or a QPen or something like that. In my case, it needs to return a class that is defined by the creator of the plugin. I'll try to explain my problem in as much detail as possible, and there is probably an easy answer. Some code might make it clearer:

    In my application, I have the following plugin interface:

    Qt Code:
    1. class viewerInterface {
    2. public:
    3. virtual ~viewerInterface() { }
    4. virtual QStringList views() const = 0;
    5. virtual QWidget * loadViewer(const QString &view_type, QString dbTable, QString dbFile) = 0;
    6. };
    7. Q_DECLARE_INTERFACE(viewerInterface,"com.software_name.app_name.viewerInterface/0.1")
    To copy to clipboard, switch view to plain text mode 

    And an intended plugin for this interface is shown below:

    Qt Code:
    1. class varMatrixReal : public QWidget, public Ui_varMatrixBase, public viewerInterface {
    2. Q_OBJECT
    3. Q_INTERFACES(viewerInterface)
    4. public:
    5. varMatrixReal(QWidget *parent = 0);
    6. void setupVUI(QString, QString); // Setup viewer user interface
    7. QStringList views() const;
    8. QWidget * loadViewer(const QString &view_type, QString dbTable, QString dbFile);
    9.  
    10. private slots:
    11. void Close();
    12. bool createDBConnection();
    13.  
    14. private:
    15. // Variables
    16. QSqlTableModel *dataModel;
    17. QSqlDatabase dbProject;
    18.  
    19. public:
    20. // Details received from application side
    21. QString dbTable;
    22. QString dbFilename;
    23.  
    24. };
    25.  
    26. #endif // !_VARMATRIXREAL_H_
    To copy to clipboard, switch view to plain text mode 

    where the classes it inherits from are the following:
    QWidget - Needed since it will be a widget displayed in a MDI Area
    Ui_varMatrixBase - GUI base class created with Qt designer
    viewerInterface - The abstract interface base class

    Now with this background the question is the following: When I want to use this plugin in my application, how is it possible to cast a pointer to the varMatrixReal class if the main application does not have any knowledge of the plugin except for the interface (or does it?).

    The first step will be something like this:
    Qt Code:
    1. QPluginLoader loader(pluginDir.absoluteFilePath(fileName));
    2. if (viewerInterface*interface = qobject_cast<viewerInterface*>(loader.instance()))
    3. interfaces.append(interface);
    To copy to clipboard, switch view to plain text mode 

    But after this, how is it possible to use the functions of the derived classes and not only the interface base class? I mean, to do this you should probably qobject_cast the interface pointer to a varMatrixReal class and add such an instance to the MDI Area, however how do I get the application to have knowledge of the varMatrixReal class? Or the more generic case where the plugin defined the needed derived class and the application does not have knowledge of this, in this case varMatrixReal.

    I have the feeling it should be possible because the plugin is a library which contains the class definition in any case. Do I only need to link to it in the .pro file perhaps?

    Thanks in advance, I hope the question is clear enough.
    Jaco

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

    Default Re: Plugin implementation question

    The widget should not inherit the plugin interface. The plugin should be a separate object inheriting QObject and the plugin interface and from its loadViewer() method you should return a new widget like varMatricReal.

  3. #3
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Plugin implementation question

    Ahhh, so the plugin and widget should be seperate. I think that makes sense and it would make things a little bit easier. Thanks!

    So the application can just add a new subwindow to the MDI area using something like the code below, without the main application needing to know the definition of the varMatrixReal class?

    Qt Code:
    1. mdiArea->addSubWindow(interface->loadViewer("Real Matrix,"table_name",active_db_file));
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Plugin implementation question

    Reading through my last post again, that is not going to work... Is it?

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

    Default Re: Plugin implementation question

    It should work provided that the plugin never returns a null pointer from loadViewer and interface contains an instance of the plugin.

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

    JPNaude (26th August 2008)

  7. #6
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Plugin implementation question

    I've tried your suggestions and I am trying to understand why it would work. I've separated the plugin and the QWidget now and my loadViewer function in the plugin (matrixViewers) returns a matrixReal instance now as shown below:

    Qt Code:
    1. matrixReal* matrixViewers::loadViewer(const QString &view_type, QString dbTable, QString dbFile) {
    2. if (view_type == "Real") {
    3. matrixReal* newViewer = new matrixReal;
    4. newViewer->setupVUI(dbTable,dbFile);
    5. return newViewer;
    6. } else {
    7. // Create a default window here which says the plugin failed to load
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 

    This makes sense but the loadViewer function is a virtual function in the interface base class. Now the question: How is the interface base class going to know anything about the matrixReal class? Isn't the main program using this interface without knowledge of the classes inside the plugin (matrixReal for example)?

    The viewerInterface is shown below:

    Qt Code:
    1. class viewerInterface {
    2. public:
    3. virtual ~viewerInterface() { }
    4. virtual QStringList views() const = 0;
    5. virtual matrixReal* loadViewer(const QString &view_type, QString dbTable, QString dbFile) = 0;
    6. };
    7. Q_DECLARE_INTERFACE(viewerInterface,"com.software_name.app-name.viewerInterface/0.1")
    To copy to clipboard, switch view to plain text mode 

    Is it possible to do it in this way?

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

    Default Re: Plugin implementation question

    Quote Originally Posted by JPNaude View Post
    How is the interface base class going to know anything about the matrixReal class?
    Why should it know anything? It knows that it implements the interface and this should be enough.

    Isn't the main program using this interface without knowledge of the classes inside the plugin (matrixReal for example)?
    Yes, that's correct.

    The viewerInterface is shown below:

    Is it possible to do it in this way?
    If your loadViewer() returns only subclasses of matrixReal objects than yes.

  9. #8
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Plugin implementation question

    Thanks again for the reply. My problem is that the interface class is used when compiling the plugin library as well as compiling the main application. In both the return type of loadViewer() need to be specified. For the plugin it makes sense to use the return type of matrixReal as shown in my previous posts.

    However for the main program, it can't use matrixReal because it does not know anything about it. This is what I don't understand... Should I use QWidget instead in the interface used to build the main program? I would think that the interface classes should be exactly the same.

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

    Default Re: Plugin implementation question

    Quote Originally Posted by JPNaude View Post
    However for the main program, it can't use matrixReal because it does not know anything about it.
    So the interface should return a QWidget pointer.

    Qt Code:
    1. class Iface {
    2. public:
    3. QWidget *getWidget() = 0;
    4. };
    5.  
    6. class Implementation : public QObject, Iface {
    7. Q_OBJECT
    8. public:
    9. QWidget *getWidget() { return new matrixReal; }
    10. };
    To copy to clipboard, switch view to plain text mode 

  11. #10
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Plugin implementation question

    Ok that helps, thanks!. I've tried this before but it did not work so I thought there was an error on my side. So I assume when you return a matrixReal pointer to a QWidget pointer it does some sort of reinterpret_cast<QWidget *> automatically.

    I'm still not 100% sure why the main program can use the QWidget pointer as a matrixReal pointer without doing a qobject_cast<matrixReal*> on it. However I believe you.

    For the moment, I am stuck where the plugin dll return a 0x1 pointer from the loadViewer() function and this pointer is useless since it bombs the program when I use it. So, I'm not sure if this is due to the way I've done my plugin or due to something else in the main program where I use the pointer.

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

    Default Re: Plugin implementation question

    Quote Originally Posted by JPNaude View Post
    've tried this before but it did not work so I thought there was an error on my side.
    Maybe you forgot to include matrixreal.h.

    So I assume when you return a matrixReal pointer to a QWidget pointer it does some sort of reinterpret_cast<QWidget *> automatically.
    Not really. As matrixReal inherits QWidget, you can always cast to the base class, so this cast is purely implicit and based on C++ rules.

    I'm still not 100% sure why the main program can use the QWidget pointer as a matrixReal pointer without doing a qobject_cast<matrixReal*> on it. However I believe you.
    This is one of C++ (or rather OO-programming) paradigms.

    For the moment, I am stuck where the plugin dll return a 0x1 pointer from the loadViewer() function and this pointer is useless since it bombs the program when I use it. So, I'm not sure if this is due to the way I've done my plugin or due to something else in the main program where I use the pointer.
    0x1 is... 1. So you must be returning an improper object (not allocated with new).

  13. #12
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Plugin implementation question

    Thanks alot for the help! I've checked and my return pointer is initialized correctly, so something else is wrong. I would need to debug it but ran out of time now. The only trace I can find at the moment is a bunch of disassembly messages like this:

    0x7c90eaf0 <ntdll!LdrDisableThreadCalloutsForDll+4>: mov (%esp),%ebx

    I've built both the library and the main app in debug mode. I'm calling the interface like this:

    Qt Code:
    1. foreach (viewerInterface *interface, viewerInterfaces) {
    2. QWidget * viewer = new QWidget(this);
    3. viewer = interface->loadViewer("Real",dropEvent->mimeData()->text(),active_db_file);
    4. try {
    5. viewer->show();
    6. }
    To copy to clipboard, switch view to plain text mode 

    And my return function in the library looks something like this, just to test it:
    Qt Code:
    1. QWidget* matrixViewers::loadViewer(const QString &view_type, QString dbTable, QString dbFile) {
    2. /*if (view_type == "Real") {
    3. matrixReal* newViewer = new matrixReal(0);
    4. newViewer->setupVUI(dbTable,dbFile);
    5. return newViewer;
    6. } else {*/
    7. // Create a default window here which says the plugin failed to load
    8. QLabel *label = new QLabel(tr("Viewer loading failed..."));
    9. QWidget *failWindow = new QWidget;
    10. QHBoxLayout *topLeftLayout = new QHBoxLayout;
    11. topLeftLayout->addWidget(label);
    12. failWindow->setLayout(topLeftLayout);
    13. failWindow->show();
    14. return failWindow;
    15. //}
    16. }
    To copy to clipboard, switch view to plain text mode 

    My knowledge of library usage is limited so I need to spend some time on it probably, if there is nothing obvious wrong with the above...

    Thanks again...

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

    Default Re: Plugin implementation question

    Instead of returning a "fail widget", return 0 and let the main application handle the fails.

Similar Threads

  1. Qt designer plugin errors on OSX Leopard
    By mpotocnik in forum Qt Tools
    Replies: 10
    Last Post: 21st January 2008, 09:45
  2. Need help making plugin
    By vieraci in forum Qt Programming
    Replies: 10
    Last Post: 24th September 2007, 13:20
  3. QPluginLoader not recognizing a plugin
    By KShots in forum Qt Programming
    Replies: 3
    Last Post: 29th June 2007, 14:13
  4. plugin loading problem
    By naresh in forum Qt Programming
    Replies: 6
    Last Post: 9th June 2007, 19:05
  5. Qt4 win opensource + mysql plugin
    By vr in forum Installation and Deployment
    Replies: 3
    Last Post: 25th May 2007, 09:01

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.