1

I try to get a QObject-subclassed object from a Qt shared library to a Qt application dynamically.

I have tried to apply a previous answer about this subject : QLibrary - import a class

Here is my common interface tabappinterface.h:

#ifndef TABAPP_H
#define TABAPP_H

#include <QObject>
#include <QWidget>

class TabAppInterface : public QObject
{
    Q_OBJECT
public:
    virtual ~TabAppInterface()
    {
    }
    QWidget *app;
    QString title;
};

#endif // TABAPP_H

My class dll-side mytabapp.h:

#ifndef MYTAB_H
#define MYTAB_H

#include "tabapp_global.h"
#include "tabappinterface.h"

class MYTABSHARED_EXPORT MyTabApp: public TabAppInterface
{
public:
    MyTabApp();
    virtual ~MyTabApp();
    QWidget *app;
    QString title;
};

extern "C" MYTABSHARED_EXPORT TabAppInterface *getTabApp();

and its implementation mytabapp.cpp:

#include "mytabapp.h"

MyTabApp::MyTabApp()
{
    app = new AppWidget();
    title = QStringLiteral("My Tab App");
}

MyTabApp::~MyTabApp()
{

}

TabAppInterface *getTabApp()
{
    return new MyTabApp();
}

My app-side implementation:

void ContainerMainWindow::loadLibraries()
{
    QLibrary myLib("mytabapp.dll");
    if(myLib.isLoaded())
    {
        qDebug() << "Loaded!";
    }
    typedef TabAppInterface *(*tabAppGetProt)();
    auto tabAppGetter = (tabAppGetProt) myLib.resolve("getTabApp");
    if(tabAppGetter)
    {
        auto *tabApp = tabAppGetter(); // not null
        qDebug() << tabApp->title; // print empty string
        qDebug() << (QWidget *)(tabApp->app); // SEGFAULT
    }
}

As stated in comment in the last lines, the object members are not retrieved although tabApp is not null.

Any idea?

Thanks!

G. Lusson
  • 15
  • 1
  • 4

1 Answers1

2

You're accessing the base class variables (fields) title and app, which nobody ever initialized. These variables aren't virtual at all, so those in the derived class just hide those in the base class. As a solution, you can declare them as protected in the base class and encapsulate them in getters and setters.

This way, your base class is like:

class TabAppInterface : public QObject
{
    Q_OBJECT
public:
    virtual ~TabAppInterface(){}

    QWidget *getApp() const { return app; }
    void setApp(QWidget *value) { app = value; }

    QString getTitle() const { return title; }
    void setTitle(const QString &value) { title = value; }

protected:
    QWidget *app;
    QString title;
};

and the derived class is just like:

class MYTABSHARED_EXPORT MyTabApp: public TabAppInterface
{
public:
    MyTabApp();
    virtual ~MyTabApp();
};

You can still directly access the variables inside the derived class (i.e. initialize them in constructor) and through the getters/setters methods from outside:

    auto *tabApp = tabAppGetter();
    qDebug() << tabApp->getTitle();
    qDebug() << tabApp->getApp();
p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35