Problem with my C++ library that uses a interface class[Solved]



  • hi,i 'm creating a C++ library that inherits from an interface,but i have met some troubles during runtime.

    it is my Interface class
    [CODE]
    #ifndef TABLEMANAGERINTERFACE_H
    #define TABLEMANAGERINTERFACE_H

    #include<QtPlugin>

    #include <QtSql/QSqlRecord>
    #include <QtSql/QSqlTableModel>
    #include <QtSql/QSqlDatabase>

    class TableManagerInterface
    {

    private:

    enum TypeModels { ReadOnlyModel,ReadWriteModel,RelationnalModel};
    

    public:
    virtual ~TableManagerInterface() {}

    virtual void setDatabase(const QSqlDatabase &database)=0;
    virtual void setTable(const QString &tablename)=0;
    virtual void select(const QString &filter=0);
    virtual void insertRecord(const QSqlRecord &record)=0;
    //virtual void editRecord(const QSqlRecord &record) =0;
    // virtual void deleteRecord(const QSqlRecord &record) =0;
    

    };

    QT_BEGIN_NAMESPACE

    Q_DECLARE_INTERFACE(TableManagerInterface,
    "com.MaxSoft.Plugin.TableManagerInterface/1.0")

    QT_END_NAMESPACE

    #endif
    [/CODE]

    now the defintion of my library class

    ItableManager.h
    [CODE]
    #ifndef ITABLEMANAGER_H
    #define ITABLEMANAGER_H

    #include "ITableManager_global.h"
    #include <QtGui/QStylePlugin>
    #include<QtSql>
    #include "interface/TableManagerInterface.h"

    class ITABLEMANAGERSHARED_EXPORT ITableManager :public QObject,public TableManagerInterface
    {
    Q_OBJECT
    Q_INTERFACES(TableManagerInterface)

    public:
    ITableManager();
    virtual ~ITableManager() {}

    private:
    QSqlDatabase db;
    QSqlTableModel *model;
    QMap<int,QString> mapKey;
    public:
    void setDatabase(const QSqlDatabase &database);
    void setTable(const QString &tablename);
    void setPrimaryKeys(QMap<int, QString> map);
    void select(const QString &filter=0);
    QSqlRecord record() const;
    void insertRecord(const QSqlRecord &record);

    signals:

    public slots:

    };

    #endif // ITABLEMANAGER_H
    [/CODE]

    ITableManager.cpp

    [CODE]
    #include "itablemanager.h"
    #include<QMessageBox>

    ITableManager::ITableManager()
    {

    }

    /*!
    Cette méthode permet de récupérer une instance de laconnexion
    à une base de donnée
    */
    void ITableManager::setDatabase(const QSqlDatabase &database)
    {
    this->db=database;
    }

    /*!

    informe sur la table et ses champs
    */
    void ITableManager::setTable(const QString &tablename)
    {
    model= new QSqlTableModel(0,this->db);
    model->setTable(tablename);
    }

    /*!
    charge le model avec les lignes
    */
    void ITableManager::select(const QString &filter)
    {
    model->setFilter(filter);
    if( !model->select() )
    qDebug()<<" Lignes non chargées";
    }

    /*!
    retourne une enregistrement contenant les infos à
    propos des colonnes(champs) de la table
    */
    QSqlRecord ITableManager::record() const
    {
    return model->record();
    }

    /*!
    spécifie les clés primaires et leurs types
    */

    void ITableManager::setPrimaryKeys(QMap<int, QString> map)
    {
    mapKey = map;
    }

    /*!

    */

    void ITableManager::insertRecord(const QSqlRecord &record)
    {

    //on verifie si la clé existe
    QString filter="WHERE ";
    
    QMapIterator<int,QString> i(mapKey);
    while (i.hasNext()) {
           i.next();
          // cout << i.key() << ": " << i.value() << endl;
           if( i.value()=="int"){
    
               filter +=  record.fieldName(i.key()) + "=" + record.value(i.key()).toInt()+ " ";
           }
           else if (i.value()=="String") {
    
               filter += record.fieldName(i.key()) + "='" + record.value(i.key()).toString() +"' ";
           }
           else if (i.value()=="Date") {
               filter += record.fieldName(i.key()) + "='"+record.value(i.key()).toDate().toString("dd/MM/yyyy")+"' ";
    
           }
           else if (i.value()=="Double") {
               filter += record.fieldName(i.key()) + "=" +record.value(i.key()).toDouble() + " ";
    
           }
           if( i.hasNext())
               filter +=" AND ";
    }
    
    this->select(filter);
    
    if (model->rowCount() != 0)
         QMessageBox::warning(0,tr("Erreur Insertion"),tr("Présence de doublons"));
    else{
    
        if( model->insertRecord(-1,record) )
            QMessageBox::information(0,tr("Insertion"),tr("Enregistré"));
        else{
    
            QMessageBox::critical(0,tr("Erreur Insertion"),tr("Echec de L'enregistrement! <br> "
                                                              "Vérifiez les valeurs.."));
            qDebug()<< model->lastError().text();
        }
    }
    

    }

    Q_EXPORT_PLUGIN2(ITableManagerPlugin,ITableManager)

    [/CODE]

    my ITableManager.pro

    [CODE]

    QT += sql

    TARGET = ITableManagerPlugin
    TEMPLATE = lib

    DEFINES += ITABLEMANAGER_LIBRARY

    SOURCES += itablemanager.cpp

    INCLUDEPATH +=interface/

    HEADERS += itablemanager.h
    ITableManager_global.h\

    DESTDIR =../lib
    [/CODE]

    so ,when i compile my program, i'm getting following errors in my application output pane

    debug\itablemanager.o:-1: In function ITableManager': itablemanager.cpp:8: error: undefined reference toTableManagerInterface::~TableManagerInterface()'
    debug\itablemanager.o:-1: In function TableManagerInterface': TableManagerInterface.h:11: error: undefined reference tovtable for TableManagerInterface'
    :-1: error: collect2: ld returned 1 exit status
    [/B]*

    Someone can you tell me what the problem?
    Thanks in advance



  • where is your tablemanager.cpp ? i only can see itablemanager.cpp.
    seems like you forgot to add something(source code or linker unit like *.a or *.lib)



  • The object code for class TableManagerInterface is missing. Yes, you do have code for that, as the destructor isn't pure virtual! You will have to link your plugin against some lib that contains the code from the interface.



  • PLease, Volker you said that 'The object code for class TableManagerInterface is missing',
    what object code?
    i have already showed all codes.



  • You showed the source code. Object code is what the compiler produces. It's glued together by the linker to a runnable application (or a library).

    Just by including the header file into another source file does not necessarily produce some object code that can be linked. I recommend to put the dummy implementation of the interface into a separate C++ file (.cpp). You will have to link its object code (xxx.o) to your project or - better - create a library out of it that you link against.



  • [quote author="Volker" date="1325265231"]You showed the source code. Object code is what the compiler produces. It's glued together by the linker to a runnable application (or a library).

    Just by including the header file into another source file does not necessarily produce some object code that can be linked. I recommend to put the dummy implementation of the interface into a separate C++ file (.cpp). You will have to link its object code (xxx.o) to your project or - better - create a library out of it that you link against.[/quote]

    How do i will do that,making dummy implementation.
    Create an another source file nammed 'TableManagerInterface.cpp' and put this code?
    @
    #include "TableManagerInterface.h"
    @
    i try it but dont work.
    Please lead me to do it..
    thanks in advance



  • You will have to move the empty body of the destructor to the .cpp file. And either include that file into your plugin project, or make it a library that you link against. I don't have a complete example at hand.



  • i did what you said and compilation works fine.
    Now i want to use my C++ library in another project .

    this is global structure of my project.

    -Folder Dao(Dao.pro,
    Folder ITableManager(itablemanager.pro,itablemanager.h,itablemanager.cpp,
    Folder interface(TableManagerInterface.h,TableManagerInterface.cpp))
    )

    -Folder ui(project which uses library class)
    (
    ui.pro, dialogArtiste.cpp,dialogArtiste.h
    )

    Now i edit the * ui.pro* file for using library.
    @

    QT +=sql

    SOURCES +=
    main.cpp

    #folders
    include(client/client.pri)
    include(contrat/contrat.pri)
    include(reservation/reservation.pri)
    include(suivi_formation/suivi_formation.pri)
    include(suivi_master/suivi_master.pri)
    include(ventes/ventes.pri)

    #library
    DEPENDPATH += Dao/ITableManager
    INCLUDEPATH += Dao/ITableManager
    LIBS += -LDao/ITableManager/debug -lITableManager

    @

    -in some parts in dialogArtiste.h i m putting following codes(i include 'itablemanager.h' and declare a 'ITableManager object')

    @
    #ifndef DIALOGARTISTE_H
    #define DIALOGARTISTE_H

    #include "ui_dialogartiste.h"

    //include for using ITableManager class
    #include "itablemanager.h"

    class DialogArtiste : public QDialog, private Ui::DialogArtiste
    {
    Q_OBJECT

    public:
    explicit DialogArtiste(QWidget *parent = 0);

    protected:
    void changeEvent(QEvent *e);
    private:
    ITableManager *manager; // declare a ITableManager(class of my library)
    };

    #endif // DIALOGARTISTE_H

    @

    then when i compile, i'm getting error like:

    :-1: error: cannot find -lITableManager
    i think that i dont put an appropriate path of my library.
    What do i should do?
    Thanks in advance.

    [quote author="Volker" date="1325338845"]You will have to move the empty body of the destructor to the .cpp file. And either include that file into your plugin project, or make it a library that you link against. I don't have a complete example at hand.[/quote]



  • [quote author="maxoreli" date="1325660608"]
    then when i compile, i'm getting error like:

    :-1: error: cannot find -lITableManager
    i think that i dont put an appropriate path of my library.
    What do i should do?
    Thanks in advance.
    [/quote]

    Search the location of libTableManager.{a,so,lib,dylib} and add this directory to the LIBS variable:

    @
    LIBS += -L/path/to/your/lib
    @



  • ok,i have done it like that.
    @
    DEPENDPATH += C:/Users/MAXORELI/Documents/QtPrograms/ENIOLASYST/Dao/ITableManager
    INCLUDEPATH += C:/Users/MAXORELI/Documents/QtPrograms/ENIOLASYST/Dao/ITableManager
    LIBS += -L/C:/Users/MAXORELI/Documents/QtPrograms/ENIOLASYST_Debug/Dao/lib/libITableManagerPlugin.a
    @
    However, i m getting following error:
    \dialogartiste.o:-1: In function DialogArtiste': \dialogartiste.cpp:8: error: undefined reference to_imp___ZN13ITableManagerC1Ev'
    \dialogartiste.cpp:8: error: undefined reference to `_imp___ZN13ITableManagerC1Ev'

    what happens i dont understand
    [quote author="Volker" date="1325691249"]
    [quote author="maxoreli" date="1325660608"]
    then when i compile, i'm getting error like:

    :-1: error: cannot find -lITableManager
    i think that i dont put an appropriate path of my library.
    What do i should do?
    Thanks in advance.
    [/quote]

    Search the location of libTableManager.{a,so,lib,dylib} and add this directory to the LIBS variable:

    @
    LIBS += -L/path/to/your/lib
    @
    [/quote]



  • That's basic C/C++ magic

    • -L (uppercase L) adds the path to a directory containing libraries
    • -l (lowercase l) add a library to the link step
      it is search in the standard system lib paths and that added via -L to your project

    I leave it as an exercise to you to split your line up into two parts.



  • -in fact my lines aren't splitted in my .pro file, they were splitted when i have posted the reply.
    this is what happens.
    when i just declare an ITableManager in .h file ,compilation works fine.

    @
    #ifndef DIALOGARTISTE_H
    #define DIALOGARTISTE_H

    #include "ui_dialogartiste.h"
    #include "itablemanager.h"

    class DialogArtiste : public QDialog, private Ui::DialogArtiste
    {
    Q_OBJECT

    public:
    explicit DialogArtiste(QWidget *parent = 0);

    protected:
    void changeEvent(QEvent *e);
    private:
    ITableManager *manager;
    };

    #endif // DIALOGARTISTE_H
    @

    after when i instantiate the ITableManager in .cpp, compilation displays errors:

    @
    #include "dialogartiste.h"

    DialogArtiste::DialogArtiste(QWidget *parent) :
    QDialog(parent)
    {
    setupUi(this);

    manager=new ITableManager;
    

    }
    @

    Errors:
    -dialogartiste.cpp:8: error: undefined reference to_imp___ZN13ITableManagerC1Ev' -dialogartiste.cpp:8: error: undefined reference to_imp___ZN13ITableManagerC1Ev'
    [quote author="Volker" date="1325780670"]That's basic C/C++ magic

    • -L (uppercase L) adds the path to a directory containing libraries
    • -l (lowercase l) add a library to the link step
      it is search in the standard system lib paths and that added via -L to your project

    I leave it as an exercise to you to split your line up into two parts.[/quote]



  • @
    LIBS += LC:/Users/MAXORELI/Documents/QtPrograms/ENIOLASYST_Debug/Dao/lib
    LIBS + -lITableManagerPlugin
    @



  • oh,thanks you so much Volker,really speaking i was so stupid for not thinking to it,now compilation works fine,but isn't it some parts where it is explained in documentation? if yes,send me link,or you have an another link which explains this notion.
    How to mark this thread like resolved?
    Thanks for reading again.
    [quote author="Volker" date="1325810603"]@
    LIBS += LC:/Users/MAXORELI/Documents/QtPrograms/ENIOLASYST_Debug/Dao/lib
    LIBS + -lITableManagerPlugin
    @
    [/quote]



  • It's not in the Qt docs (despite some usage in examples). It's compiler dependent and documented with those, although most tool chains use -l and -L for the libs and lib paths, and -I for include paths. I don't know of any popular compiler that doesn't support this (at least additionally to some "native" switches like /xxx). It should be explained detailed in quite all decent introductions into C/C++ programming.

    To mark a thread as solved, just go to your very first post that opened the thread, click on the edit link right to it (just below your username and avatar) and prepend [Solved] to your topic, that's all. You might want to add a tag "solved" too.


Log in to reply
 

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