I have some functions in delphi dll, and I want to load them (using QtLibrary) at once.
Can I store that functions in global variables to use it? I tried to declare global function pointer in .h file and resolve them in main file, but got error "multiple definition"
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qlibrary.h>
#include <QDebug>
#include "mapwidget.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString path = "map_dll.dll";
if (QLibrary::isLibrary(path)) {
lib = new QLibrary(path);
lib->load();
if (!lib->isLoaded()) {
qDebug() << lib->errorString();
} else {
nearestWell = (void( *)(double x,
double y,
double &wellX,
double &wellY))
lib->resolve("nearestWell");
}
}
}
void MainWindow::on_pushButton_2_clicked()
{
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLibrary>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QLibrary *lib;
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mapwidget.h
#ifndef MAPWIDGET_H
#define MAPWIDGET_H
#include <QWidget>
#include <QPainter>
typedef void (*NearestWellFunc) (double x, double y, double &wellX,
double &wellY);
extern NearestWellFunc nearestWell;
....
#endif // MAPWIDGET_H
error message:
debug/mainwindow.o: In function `ZN10MainWindow21on_pushButton_clickedEv':
C:\nipi\APT\map_qt\build-MIG-Desktop_Qt_5_1_0_MinGW_32bit-Debug/../MIG/mainwindow.cpp:33: undefined reference to `nearestWell'
C:\nipi\APT\map_qt\build-MIG-Desktop_Qt_5_1_0_MinGW_32bit-Debug/../MIG/mainwindow.cpp:40: undefined reference to `nearestWell'
C:\nipi\APT\map_qt\build-MIG-Desktop_Qt_5_1_0_MinGW_32bit-Debug/../MIG/mainwindow.cpp:54: undefined reference to `nearestWell'
Makefile.Debug:84: recipe for target 'debug/MIG.exe' failed
mingw32-make[1]: Leaving directory 'C:/nipi/APT/map_qt/build- MIG-Desktop_Qt_5_1_0_MinGW_32bit-Debug'
makefile:34: recipe for target 'debug' failed
C:\nipi\APT\map_qt\build-MIG-Desktop_Qt_5_1_0_MinGW_32bit-Debug/../MIG/mainwindow.cpp:63: undefined reference to `nearestWell'
collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: *** [debug/MIG.exe] Error 1
mingw32-make: *** [debug] Error 2
This error:
undefined reference to `nearestWell'
Is the compiler saying "I know that there is a thing called nearestWell, but I don't know where it is stored (because it hasn't been defined)"
This line:
extern NearestWellFunc nearestWell;
Says to the compiler "somewhere else there will be a NearestWellFunc called nearestWell".
This is a declaration - it is telling the compiler that there will be a variable called nearestWell somewhere later.
It needs to be paired with a definition that tells the compiler to set aside some space for the variable. In this case, it would look something like:
NearestWellFunc nearestWell = /* whatever the initial value should be */
Remember, you can only define things once, or the compiler will get confused. This is why you need to put the declaration inside a .cpp file rather than the .h file - if you put the definition in the header file, each .cpp file that includes that header will include the definition, which is what is causing the multiple definition error.
Looking at your example structure, I would put the definition in mainwindow.cpp.
You can declare the variables in a header file, but you can't define them.
For example, declaring a variable as extern in a header file is fine. You probably define them instead. Add the extern keyword to your declarations in the header file, and add definitions in a source file.
Related
Good day all
Please note: C++ newbie here
I am creating shared libraries among various other c++ features to allow for a complete understanding, however I am at a loss.
Problem:
As the title suggests, a list of errors:
I have no idea what causes them, and googling does not provide much insight either. As suggested here to add the Q_Object macro, I have done so but obviously it is of no use.
Various other SO posts suggest checking the correct header, etc which is correct.
Error:
netm.cpp:3: error: undefined reference to `vtable for netm'
netm.cpp:3: error: undefined reference to `_imp___ZN4miscC1Ev'
netm.cpp:6: error: undefined reference to `vtable for netm'
netm.cpp:6: error: undefined reference to `_imp___ZN4miscC1Ev'
//...
I have several more errors similar to these above, but solving these should assist me in resolving the rest
From all the tutorials, etc I have followed, I have done nothing out of the ordinary.
Note: I am unsure what information is all required, if more is required, I'll gladly share.
//.pro
QT -= gui
QT += network
TARGET = netm
TEMPLATE = lib
DEFINES += NETM_LIBRARY
SOURCES += netm.cpp
HEADERS += netm.h\
netm_global.h
unix {
target.path = /usr/lib
INSTALLS += target
}
//netm_global.h - FULL
#ifndef NETM_GLOBAL_H
#define NETM_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(NETM_LIBRARY)
# define NETMSHARED_EXPORT Q_DECL_EXPORT
#else
# define NETMSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // NETM_GLOBAL_H
//netm.h - FULL
#ifndef NETM_H
#define NETM_H
#include "netm_global.h"
#include "../misc/misc.h"
#include "../gen/gen.h"
#include <QHostInfo>
#include <QTcpSocket>
class NETMSHARED_EXPORT netm
{
Q_OBJECT
public:
netm();
netm(QString hostname);
bool Send(int portNumber, char* message = NULL);
ReturnObject read();
bool isServerOnline(QString IP = QString());
int getPing(QString IP = QString());
void getIP();
void disconnectFromServer();
~netm();
private slots:
void getIP();
private:
misc m;
QHostInfo serverInfo;
QHostAddress serverIP;
QTcpSocket tcp_con;
};
#endif // NETM_H
//netm.cpp - Partial
#include "netm.h"
netm::netm(){ <--- ERROR line
}
netm::netm(QString hostname) <--- ERROR line
{
serverInfo.lookupHost(hostname, 0, SLOT(getIP()));
}
//...
Help (with explanations) would be greatly appreciated!
UPDATE
As suggested, I defined the constructor in misc.cpp, since it was not present.
Recompiling, I read an error mentioning that the netm class needed to inherit from QObject.
Thus adding/changing:
//netm.h - Partial
#include //...
#include <QObject>
class NETMSHARED_EXPORT netm : public QObject
{
Q_OBJECT
public:
netm();
netm(QString hostname);
//...
};
Errors persist:
netm.cpp:3: error: undefined reference to `_imp___ZN4miscC1Ev'
netm.cpp:3: error: undefined reference to `_imp___ZN4miscD1Ev'
netm.cpp:6: error: undefined reference to `_imp___ZN4miscC1Ev'
netm.cpp:6: error: undefined reference to `_imp___ZN4miscD1Ev'
For completeness sake (misc is also a dynamic library):
//misc.h
#ifndef MISC_H
#define MISC_H
#include "misc_global.h"
#include <QString>
#include <QList>
class MISCSHARED_EXPORT misc
{
public:
misc();
~misc();
//String Literals
//Network related
static QString googleDNS;
//Command Codes
static QString CMD_AUTH;
static QString CMD_REQ;
//Request Codes
static QString REQ_USER_INFO;
static QString REQ_VPN_DATA;
static QString REQ_VPN_UP;
//...
};
//misc.cpp
#include "misc.h"
misc::misc(){
//Network related
QString googleDNS = QStringLiteral("8.8.8.8");
//Command Codes
QString CMD_AUTH = QStringLiteral("AUTH");
QString CMD_REQ = QStringLiteral("REQ");
//Request Codes
QString REQ_USER_INFO = QStringLiteral("USER_INFO");
QString REQ_VPN_DATA = QStringLiteral("VPN_DATA");
QString REQ_VPN_UP = QStringLiteral("VPN_UP");
}
misc::~misc(){}
As seen here, the constructor exists,
any other thoughts?
Missing calls to _imp___ZN4miscC1Ev, which is misc::misc() according to c++filt, likely means that the class misc is missing a defined default constructor. Check to make sure you're compiling in a definition for misc::misc().
For the vtable error, make sure that you've provided a definition (even if empty or stubbed out) for every function declared in netm (or at minimum all of the virtual functions in netm). The vtable for a class references every virtual function, so all of the virtual functions must be defined or it will not compile.
This is about a Qt 5.3.2 project buildt using CMake.
I have designed a QMainWindow using the Qt Designer, leading
to main.ui.
CMakeLists.txt (the almost complete thing may be
found here where I already posted it for a different question:
Linking and UIC order in a CMake Qt project )
already takes care of calling UIC so I have my hands on ui_main.h.
ui_main.h offers the class Ui::MainWindow with the plain form information
where all the buttons and stuff should be and the method *void setupUi(QMainWindow MainWindow).
Now my workflow (is it even a feasible one?) goes like this:
I build a totally new header file Form_main.h:
// Form_main.h
[..]
class Form_main : public MainWindow, public QMainWindow
{
Q_OBJECT
privat slots:
void on_some_event();
[..]
};
The class uses said auto-generated MainWindow::setupUi(this) to 'get in shape' and QMainWindow to be, well, a QMainWindow with all that stands for.
But now I am in a dilemma: Either I remove the Q_OBJECT macro call leading to connect(..) no longer recognizing that Form_main has signal slots, or
I keep the Q_OBJECT leading to the infamous
undefined reference to `vtable for display::Form_main'
error while linking the project.
Now, there have been, in fact, people with similar issues.
Naming some links:
http://michael-stengel.com/blog/?p=103
Qt Linker Error: "undefined reference to vtable"
Undefined reference to vtable... Q_OBJECT macro
Qt vtable error
A hint I got from the last one: "MOC must generate code for ui_main.h and the generated code must be compiled and linked."
In any case, these answers all seem to boil down to 'running qmake again'. Well, I use CMake all the way wanting my project to configure and compile after exactly
cmake .
make
What I did try was deleting everything in and below the build directory
(including every auto-generated file) and then running cmake . && make;.
Sadly that did not help. I am afraid this is my second noob question today... would you bear with me once more?
=== AFTER TRYING GREENWAYS ANSWER I PROVIDE MORE DETAILS. ===
Here is the autogenerated ui_main.h
/********************************************************************************
** Form generated from reading UI file 'main.ui'
**
** Created by: Qt User Interface Compiler version 5.3.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAIN_H
#define UI_MAIN_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
[.. more Widget Includes ..]
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QAction *action_exit;
[.. more sub widgets like that .. ]
void setupUi(QMainWindow *MainWindow)
{
[ .. Setting up the form. Harmless code. .. ]
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
[ .. completely harmless .. ]
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAIN_H
Reading all this and incorporating your post right now I am at
// form_main.h
#ifndef MHK_FORM_MAIN_H
#define MHK_FORM_MAIN_H
#include <QMainWindow>
#include "ui_main.h"
[..]
namespace Ui { class MainWindow; }
namespace display
{
class Form_main : public QMainWindow
{
Q_OBJECT
private:
ostream* stdout;
ostream* stderr;
Ui::MainWindow* uiMainWindow;
/** Called by the constructor. Sets up event connections and other
* preliminary stuff the qt Designer is overtasked with. */
void setup_form();
[..]
public:
explicit Form_main(QWidget* parent = 0);
~Form_main();
private slots:
void exit_program();
};
}
#endif
And my cpp
// form_main.cpp
#include "ui_main.h"
#include "form_main.h"
[..]
using namespace Ui;
namespace display
{
void Form_main::setup_form()
{
QObject::connect(uiMainWindow->action_exit, SIGNAL(triggered()), this, SLOT(exit_program()));
[..]
}
Form_main::Form_main(QWidget* parent) : QMainWindow(parent)
{
uiMainWindow = new Ui::MainWindow();
uiMainWindow->setupUi(this);
[..]
#if defined(Q_OS_SYMBIAN)
this->showMaximized();
#else
this->show();
#endif
}
Form_main::~Form_main()
{
delete uiMainWindow;
}
[..]
Form_main::exit_program()
{
this->close();
(*stdout) << "Thanks for playing " << getProgramName() << endl;
}
}
Ok. I see (partly) the problem. Just create a widget class like this:
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
This is how the QtCreator creates ui-Widgets. "ui_MainWindow.h" is your generated .h file.
Thanks for all your help! However, the problem was in CMakeLists.txt after all. The comment of Chris Morlier on Undefined reference to vtable pointed me to the solution.
The pertinent passage goes:
For Qt users: you can get this same error if you forget to moc a header
I simply had to add the header form_main.h into this line:
QT5_WRAP_CPP(qt_H_MOC ${qt_H} "${DIR_SRC}/include/form_main.h")
If I define the function in mainwindow.cpp the function works, but when I define it in radiobuttons.cpp, and attempt to call it from mainwindow.cpp, the project won't compile.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void build_radios(); //this function
~MainWindow();
};
#endif // MAINWINDOW_H
radiobuttons.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
void MainWindow::build_radios()
{
//... some code
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
void MainWindow::radio_buttons(); //error: C2761: 'void MainWindow::build_radios(void)' : member function redeclaration not allowed
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
radio_buttons();
}
That's not a definition, the compiler sees it as a declaration of a member function outside the class definition, which is illegal. Just remove that line. It shouldn't be there in the first place, it has no use.
In fact, move the actual definition from radiobuttons.cpp to mainwindow.cpp for consistency. Why declare a MainWindow member in a different implementation file?
but when I define it in radiobuttons.cpp...
Except that you don't define but re-declare it. (And even that's redundant since you have the header file of the class included in that particular file.) The error message says pretty much what the problem is:
member function redeclaration not allowed
When you declare the MainWindow class, you have the void build_radios(); declaration inside - that in itself is enough for declaring the method. In the .cpp file, it's sufficient to implement it only, i. e. provide a definition only - you already have a declaration, coming from declaration of the class in the header file.
(In fact, you also have a definition, but that's in the radiobuttons.cpp file - it should be in the mainwindow.cpp. Fit all the methods of a class into one implementation file, don't speread them across multiple files and classes and... and... and...)
I keep getting this error:
cannot call member function 'QString Load::loadRoundsPlayed()'without object
Now im pretty new to c++ and qt so im not sure what this means. I am trying to call a function from another class to set the number on some lcdNumbers. Here is the Load.cpp which holds the function:
#include "load.h"
#include <QtCore>
#include <QFile>
#include <QDebug>
Load::Load() //here and down
{}
QString Load::loadRoundsPlayed()
{
QFile roundsFile(":/StartupFiles/average_rounds.dat");
if(!roundsFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug("Could not open average_rounds for reading");
}
Load::roundsPlayed = roundsFile.readAll();
roundsFile.close();
return Load::roundsPlayed;
}
And here is the Load.h:
#ifndef LOAD_H
#define LOAD_H
#include <QtCore>
class Load
{
private:
QString roundsPlayed; //and here
public:
Load();
QString loadRoundsPlayed(); //and here
};
#endif // LOAD_H
And finally the place where i call the function:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "load.h"
#include <QLCDNumber>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MainWindow::startupLoad();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::startupLoad()
{
ui->roundPlayer_lcdNumber->display(Load::loadRoundsPlayed()); //right here
}
When i run this i get that error. Im not sure what it means so if anyone could help i would be thankfull. Thanks.
The error description is pretty clear
cannot call member function 'QString Load::loadRoundsPlayed()'without object
You cannot call member functions, that are not static, without creating instance of the class.
Looking at you code, you probably need to do this:
Load load;
ui->roundPlayer_lcdNumber->display(load.loadRoundsPlayed()); //right here
There are two other options:
make loadRoundsPlayed static and roundsPlayed static, if you don't want them to be associated with the concrete instances OR
make loadRoundsPlayed static and return QString by copy, that will be locally created inside the function. Something like
:
QString Load::loadRoundsPlayed()
{
QFile roundsFile(":/StartupFiles/average_rounds.dat");
if(!roundsFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug("Could not open average_rounds for reading");
}
QString lRoundsPlayed = roundsFile.readAll();
roundsFile.close();
return lRoundsPlayed;
}
Because the method and member are not associated with class instances, make it static:
class Load
{
private:
static QString roundsPlayed;
public:
Load();
static QString loadRoundsPlayed();
};
If you want them to be associated with instances, you'll need to create an object and call the method on it (it doesn't have to be static in this case).
In Load::loadRoundsPlayed(), you should change
Load::roundsPlayed = roundsFile.readAll();
to
this->roundsPlayed = roundsFile.readAll();
or simply
roundsPlayed = roundsFile.readAll();
This particular example won't fix the compiler error, but it illustrates where you are having some confusion with the syntax. When you prefix a function or variable name with "Load::", you are saying that you want the field that belongs to this class. However, every object of a class will have its own copy of the variables that you have declared in it. This means that you need to create an object before you can use them. Similarly, functions are bound to objects, so you again need an object in order to call a member function.
The other option is to make your functions static so that you don't need an object to call it. I strongly encourage you to learn about the difference between instance functions and static functions of a class so that you can use these two tools appropriately when the situation calls for it.
Just a Qt Gui Application with QDialog as the Base Class, the simplest type you can expect.
I've programmed on Qt for several times but this is the first time I meet this problem...
I've added minimal code to the program, and here's the code in dialog.h (which is mostly automatically generated)
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPixmap>
#include "bmp.h"
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_openButton_clicked();
private:
Ui::Dialog *ui;
BMP srcImage;
QImage compressedImage[3];
};
#endif // DIALOG_H
While I edit, the "public:" is underlined and says "unexpected token '('". When I try to build the program, it says in the line "Q_OBJECT", "error: expected ',' or '...' before numeric constant". I'm sure I've defined nothing related to it (to be exact, I defined an N and an n in file bmp.h, both are int).
Any idea of what's wrong here?
I think I've figured it out myself.
I included some
#pragma pack(push)
#pragma pack(1)
//...
#pragma pack(pop)
in file "bmp.h". When I move the line
#include "bmp.h"
into file "dialog.cpp", everything works well