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 2016

    @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
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.