[solved] Unresolved external symbol using QTableWidget



  • HI all,
    I'm suddenly getting an unresolved external symbol when compiling when I use a QTableWidget. Specifically, when I'm trying to set the row and the column count (setRowCount, and setColumnCount). I was using a QTableWidget just fine before. Then I did a bit of refactoring, and boom, unresolved external symbol.

    To resolve this, I attempted the following: deleted my build folder, reran qmake, then a full build. But I still had unresolved external symbols. I then thought to create a brand new project in the hopes to be able to compare the .pro files. I added a QTreeWidget, a QTableWidget, then edited the mainwindow.cpp to make calls to setRowCount and setColumnCount. I then ran qmake, then built the project, and somehow I'm still get unresolved external symbol in the brand new project. So, I'm clearly doing something wrong here. But I'm unclear as to how to move forward.

    I don't have a great deal of QT experience. So please, when you offer suggestions, be sure to include the newbie mistakes in your suggestions, as it's probably something very simple that I'm not doing.

    I'm using QT Creator 5.5 on Windows 8
    Does anybody have any suggestions for me?

    Here's my .pro file (automatically generated comment header and line spaces removed):

    QT       += core gui
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    TARGET = FinancialExplorerv2
    TEMPLATE = app
    SOURCES += main.cpp\
            mainwindow.cpp
    HEADERS  += mainwindow.h
    FORMS    += mainwindow.ui
    

    Here's a copy of my mainwindow.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->tableWidget->setRowCount( 100 );
        ui->tableWidget->setColumnCount( 10 );
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    As you can see, all I added was the calls to setRowCount and setColumnCount. And the error messages in the IDE after compilation are:

    For the setRowCount function:

    mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl QTableWidget::setRowCount(unsigned __int64)" (__imp_?setRowCount@QTableWidget@@QEAAX_K@Z) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow@@QEAA@PEAVQWidget@@@Z)
    

    And the setColumnCount function:

    mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl QTableWidget::setColumnCount(unsigned __int64)" (__imp_?setColumnCount@QTableWidget@@QEAAX_K@Z) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow@@QEAA@PEAVQWidget@@@Z)
    

    This is from the brand new project. This seems much simpler to troubleshoot than the original project since there's basically nothing in this one. I figure if I can solve the problem in the brand new project, then the solution should be the same for the original project.

    Thanks!



  • HI and welcome to devnet,

    can you post your code? and also the compiler output?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Since you refactored the code you probably moved things around. What did you modify exactly and how ?



  • @mcosta Sure! I edited the original question and added the information you requested.


  • Lifetime Qt Champion

    unsigned __int64 ? Looks suspicious, setRowCount uses an int



  • @SGaist Thanks for helping out, SGaist! I figure it's probably easier to troubleshoot the new project since it's the exact same issue, and there's so little in the new project. I edited the original post to add more information, including the full .pro file and the mainwindow.cpp file. Hope this helps answer your question.



  • @SGaist That's what I thought too. I've tried casting to a size_t, which is what the header for setRowCount uses. But that didn't affect the error message. I'm building using the MSVC 2013 64-bit toolkit. There were four options, 64 vs. 32 bit, and VC 2012 / VC 2013. Out of those options I prefer the one I chose, but in the interest of troubleshooting, I also tried some of the other options. But I was unable to use any of the other options as attempting to compile using the other options throws an error stating: "Qt creator needs a compiler set up to build." This tells me that I didn't accidentally switch to a different toolkit sometime in the middle of development and that's why I'm now getting this error. If I did switch to another toolkit, then I'd have had to set one up.


  • Lifetime Qt Champion

    What header ? setRowCount uses an int



  • @SGaist Well THAT's weird. I had ctrl+clicked on setRowCount before, and the header file said it used a size_t in the qtablewidget.h file. But when I ctrl+click on setRowCount in the new project, the qtablewidget.h file has the parameter as an int. What gives?

    Regardless of that, your last comment had me thinking it might be type related. So I also tried declaring an __int32, and passed that variable in. That didn't work. I also tried a number of other types, such as regular int, size_t again, and unsigned __int32. Nothing changed.


  • Lifetime Qt Champion

    Can you share your code ?



  • @SGaist I already posted the code for the brand new project. But here's the mainwindow.cpp file from the old pre-existing project:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <qtreewidget.h>
    #include <QtDebug>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        CurrentlySelectedAccount( nullptr )
    {
        financials::TheCalculator* calc = new financials::TheCalculator();
    
        QString filename( "C:\\source\\QT_Projects\\FinancialExplorer\\InputFinancials.ini" );
        calc->ParseInputFile( filename );
        this->CurrentSimulation = calc;
    
        ui->setupUi(this);
        ui->Accounts->setAnimated( true );
    
        auto AccountsMap = calc->GetAccounts();
        auto iter = AccountsMap.begin();
        QTreeWidget* accounts = ui->Accounts;
        bool isFirst = true;
        auto selectedIter = AccountsMap.begin();
        while( iter != AccountsMap.end() )
        {
            QTreeWidgetItem* item = new QTreeWidgetItem( accounts, 2 ); // 2 means "Don't show expander if no children"
    
            item->setText( 0, calc->GetName() );
    
            // add properties
            QTreeWidgetItem* StartDateItem = new QTreeWidgetItem( item, 0 );
            QString startDateLabel( "Start Date:" );
            startDateLabel.append( calc->GetStartDate().toString());
            StartDateItem->setText( 0, startDateLabel );
    
            QTreeWidgetItem* EndDateItem = new QTreeWidgetItem( item, 0 );
            QString EndDateLabel( "End Date:" );
            EndDateLabel.append( calc->GetEndDate().toString());
            EndDateItem->setText( 0, EndDateLabel );
    
            QTreeWidgetItem* CurrentDateItem = new QTreeWidgetItem( item, 0 );
            QString CurrentDateLabel( "Current Date:" );
            CurrentDateLabel.append( calc->GetCurrentDate().toString());
            CurrentDateItem->setText( 0, CurrentDateLabel );
    
            // add accounts
            QTreeWidgetItem* accountsItem = new QTreeWidgetItem( item, 2 );
            accountsItem->setText( 0, "Accounts" );
            for( auto& account : calc->GetAccounts() )
            {
                QTreeWidgetItem* accItem = new QTreeWidgetItem( accountsItem, 2 );
                accItem->setText( 0, account.second.GetName() );
                accItem->setText( 1, "I'm an account description" );
            }
    
            // add events
            QTreeWidgetItem* eventsItem = new QTreeWidgetItem( item, 2 );
            eventsItem->setText( 0, "Events" );
            for( auto& event : calc->GetEvents() )
            {
                QTreeWidgetItem* eventItem = new QTreeWidgetItem( eventsItem, 2 );
                eventItem->setText( 0, event.GetName() );
                eventItem->setText( 1, "I'm an event description" );
            }
            item->setText(1, "I'm a description");
            if( isFirst )
            {
                item->setSelected( true );
                selectedIter = iter;
                isFirst = false;
            }
            ++iter;
        }
    
        connect(ui->Accounts,&QTreeWidget::itemClicked,this,&MainWindow::on_MyTree_itemClicked);
    
        RefreshTable();
    }
    
    void MainWindow::RefreshTable()
    {
        financials::TheCalculator* calc = CurrentSimulation;
        if( calc != nullptr )
        {
            size_t lengthOfSimulation = calc->GetLengthOfSimulation();
            ui->Spreadsheet->setRowCount( lengthOfSimulation );
            size_t accountsSize = calc->GetAccounts().size();
            ui->Spreadsheet->setColumnCount( accountsSize );
    
            int rowIndex = 0;
            while( calc->IsRunning() )
            {
                QString value;
                auto accounts = calc->GetAccounts();
                auto accountsIter = accounts.begin();
                int colIndex = 0;
                while( accountsIter != accounts.end() )
                {
                    value = QString::number( (*accountsIter).second.GetCurrentBalance() );
                    ui->Spreadsheet->setItem(rowIndex, colIndex++, new QTableWidgetItem( value ));
                    ++accountsIter;
                }
                calc->IncrementMonth();
                ++rowIndex;
            }
        }
    }
    
    void MainWindow::on_MyTree_itemClicked ( QTreeWidgetItem * item, int column )
    {
        qDebug() << "on_MyTree_itemClicked"
            << item->text(column);
        //to do somthing
    
        QString text = item->text(column);
        if( CurrentSimulation != nullptr )
        {
            auto iter = CurrentSimulation->GetAccounts().find( text );
            if( iter != CurrentSimulation->GetAccounts().end() )
            {
                if( CurrentAccountName != text )
                {
                    CurrentAccountName = text;
                    CurrentlySelectedAccount = &((*iter).second);
                    RefreshTable();
                }
            }
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    

    And here's the .pro file from the old project:

    #-------------------------------------------------
    #
    # Project created by QtCreator 2015-08-26T18:06:52
    #
    #-------------------------------------------------
    
    QT       += core gui widgets
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = FinancialExplorer
    TEMPLATE = app
    
    
    SOURCES += main.cpp\
            mainwindow.cpp \
        accounts.cpp \
        thecalculator.cpp \
        financials.cpp \
        events.cpp
    
    HEADERS  += mainwindow.h \
        accounts.h \
        financials.h \
        thecalculator.h \
        events.h \
        qstringhashfunction.h
    
    FORMS    += mainwindow.ui
    
    DISTFILES += \
        InputFinancials.ini
    
    

  • Lifetime Qt Champion

    Do you also experience the same problem if you create a new project and use QTableWidget in it ?



  • @SGaist Yes. It appears that I do. I just created a brand new project with nothing in it but the QTableWidget. When I added lines to call setRowCount and setColumnCount I got the same error.

    Does this mean I have something misconfigured?


  • Lifetime Qt Champion

    I wonder if you don't have your Qt headers corrupted



  • @SGaist Yup, looks like that was it. I uninstalled Qt and reinstalled it and that fixed everything.


  • Lifetime Qt Champion

    Great :)

    By the way, since the last forum update, you can use the Topic Tool button to mark your thread as solved :)


Log in to reply
 

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