Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

undefined reference in a shared class between plugin and app.



  • Hi all,
    I want to use a class shared between plugins and a main app.
    But when I try to compil, I have this error:

    plugins\plugin01\plugin01.cpp:13: erreur : undefined reference to `CommonParameter::CommonParameter()'
    

    I must have a LIBS problem somewhere in a .pro file or something else

    Thanks in advance,
    Filipe

    Code:

    /testplugin.pro

    TEMPLATE = subdirs
    SUBDIRS += \
        src \
        plugins
    

    /src/src.pro

    TARGET          = testplugin
    DESTDIR         = ../bin
    TEMPLATE        = app
    QT    	       -= gui
    HEADERS += \
        iplugin.h \
        commonparameter.h
    SOURCES += \
        main.cpp \
        commonparameter.cpp
    
    qtHaveModule(uitools):!embedded: QT += uitools
    else: DEFINES += QT_NO_UITOOLS
    
    build_all:!build_pass {
        CONFIG -= build_all
        CONFIG += release
    }
    CONFIG   += console
    CONFIG   -= app_bundle
    

    /src/iplugin.h

    #ifndef IPLUGIN_H
    #define IPLUGIN_H
    
    #include <QtPlugin>
    #include <commonparameter.h>
    
    class QString;
    
    class IPlugin
    {
    public:
        virtual ~IPlugin() {}
    
        virtual QString name() const = 0;
        virtual CommonParameter *parameter() = 0;
    };
    
    #define IPlugin_iid "AntunesFilipe.TestPlugin.IPlugin"
    Q_DECLARE_INTERFACE(IPlugin, IPlugin_iid)
    
    #endif // IPLUGIN_H
    

    /src/main.cpp

    #include <QCoreApplication>
    #include <QTextStream>
    #include <QDir>
    #include <QPluginLoader>
    #include "iplugin.h"
    #include "commonparameter.h"
    int main(int argc, char *argv[])
    {    
       QCoreApplication app(argc, argv);
    
        // Find plugins located in a repository folder and load them...
        QDir pluginsDir = QDir(qApp->applicationDirPath());
        pluginsDir.cd("plugins");
        foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
            QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
            QObject *plugin = loader.instance();
            if (plugin) {
                IPlugin *iPlugin = qobject_cast<IPlugin *>(plugin);
                if (iPlugin) {
                    QTextStream(stdout) << "> Plugin name:" << iPlugin->name() << endl;
    
                    // !!! Waiting for: Fix undefined reference to CommonParameter::CommonParameter()
                    // CommonParameter *param = plugin->parameter();
                    // QTextStream(stdout) << "         user:" << param->userName() << endl;
                    // QTextStream(stdout) << "     password:" << param->password() << endl;
                }
            }
        }
    
        return 0;
    }
    

    Here the "sharded" class:
    /src/commonparameter.h

    #ifndef COMMONPARAMETER_H
    #define COMMONPARAMETER_H
    #include <QString>
    class CommonParameter
    {
    public:
        CommonParameter();
        void setUserName(const QString& name);
        void setPassword(const QString& password);
        QString userName() const;
        QString password() const;
    private:
        QString m_userName;
        QString m_password;
    };
    #endif // COMMONPARAMETER_H
    

    /src/commonparameter.cpp

    #include "commonparameter.h"
    CommonParameter::CommonParameter(){}
    void CommonParameter::setUserName(const QString& name)
    {
        m_userName = name;
    }
    void CommonParameter::setPassword(const QString& password)
    {
        m_password = password;
    }
    QString CommonParameter::userName() const
    {
        return m_userName;
    }
    QString CommonParameter::password() const
    {
        return m_password;
    }
    

    And a plugin:
    /plugins.pro

    TEMPLATE = subdirs
    SUBDIRS += \
        plugin01 \
    

    /plugins/plugin01/plugin01.pro

    TEMPLATE      = lib
    CONFIG       += plugin
    QT           += widgets
    INCLUDEPATH  += ../../src
    HEADERS += plugin01.h
    SOURCES += plugin01.cpp
    TARGET        = $$qtLibraryTarget(plugin01)
    DESTDIR       = ../../bin/plugins
    

    /plugins/plugin01/plugin01.h

    #ifndef PLUGIN01_H
    #define PLUGIN01_H
    #include <QObject>
    #include <QtPlugin>
    #include <iplugin.h>
    class Plugin01 : public QObject, IPlugin
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(IID "AntunesFilipe.TestPlugin.Plugin01.IPlugin" FILE "plugin01.json")
        Q_INTERFACES(IPlugin)
    public:
        Plugin01();
        QString name() const Q_DECL_OVERRIDE;
        CommonParameter *parameter() Q_DECL_OVERRIDE;
    };
    #endif // PLUGIN01_H
    

    /plugins/plugin01/plugin01.cpp

    #include "plugin01.h"
    #include <QWidget>
    
    Plugin01::Plugin01(){}
    
    QString Plugin01::name() const
    {
        return QString ("My Plugin 01");
    }
    
    CommonParameter *Plugin01::parameter()
    {
        CommonParameter *param = new CommonParameter(); // ?!? <-- undefined reference to `CommonParameter::CommonParameter()'
        param->setUserName(QString ("TEST"));
        param->setPassword(QString ("123456"));
    
        return param;
    }
    

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Did you base your application on the echo plugin example ?



  • Hi SGaist

    Yes I have based my application on echo plugin and Plug & Paint example.

    Under windows with mingw, I can not compile the project, I have this message:

    plugins\plugin01\plugin01.cpp:13: erreur : undefined reference to `CommonParameter::CommonParameter()'
    

    Under linux, with g++(4.8.5) the compilation is done but when I execute, I have this message:

    ./testplugin: symbol lookup error: ???/plugins/libplugin01.so: undefined symbol: _ZN15CommonParameterC1Ev
    

    In my first post, I made a mistake in the copy of the code:

    src/main.cpp
    -- CommonParameter * param = plugin->parameter();
    has to be replaced by
    ++ CommonParameter * param = iPlugin->parameter();
    


  • I am not sure of my "hack" but..it works if I add this line in my .pro application:

    QMAKE_LFLAGS   += -rdynamic
    

    But Why ?!?


  • Lifetime Qt Champion

    The problem you are having is that you are using a class that must be known to both your application and plugin. The clean way to do that is to have a library implementing the stuff that is used in both and link each to it.

    Basically add another sub-project for a library that will contain CommonParameter.



  • Thank You SGaist
    I think I will keep my current "dirty way", after all my application is the common module.



  • Well...I confirm. It is necessary to cut the application in sub-project.
    -rdynamic is not supported by OSX and Windows (!= ELF format)


  • Qt Champions 2017

    @Filipe-Antunes said in undefined reference in a shared class between plugin and app.:

    -rdynamic is not supported by OSX and Windows (!= ELF format)

    As is expected. The ABI on Windows is different enough and symbol resolution is done at link-time so it couldn't work. Follow @SGaist's advice and export the common classes from a library; that's the reason libraries were invented in the first place.

    Kind regards.


Log in to reply