Plugin compiler error: undefined reference
Hi, all! I want to put all UI components into one dll so I try to create a plugin. Then my folder tree is:
/ --- test.pro
|
ui ---- ui.pro
| | -- mainwindow.h
| | -- mainwindow.cpp
| | -- ivisible.h // this contains the interface that has only two functions: setVisible(bool) and visible()
|
app ----- app.pro
| --- main.cpp
| --- mainwindow.h // copy from ui/mainwindow.h
and the code is:
test.pro
Code:
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += ui app
app.pro
Code:
TARGET = test
TEMPLATE = app
CONFIG += debug
SOURCES += main.cpp
HEADERS += mainwindow.h
LIBS += -LE:\documents\test\app\plugins -lui
main.cpp
Code:
#include <QtGui/QApplication>
#include <QPluginLoader>
#include <QMessageBox>
#include <QDir>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QDir dir
(a.
applicationDirPath ());
dir.cdUp();
dir.cd("plugins");
QObject *plugin
= loader.
instance();
if(plugin) {
MainWindow *win = qobject_cast<MainWindow *>(plugin);
win->setVisible(true);
} else {
QMessageBox::information(NULL,
"load error", loader.
errorString());
}
loader.unload();
return a.exec();
}
mainwindow.h
Code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "ivisible.h"
namespace Ui {
class MainWindow;
}
class MainWindow
: public QMainWindow,
public IVisible
{ Q_OBJECT
Q_INTERFACES(IVisible)
public:
~MainWindow();
void setVisible(bool v) { if(v) this->show(); else this->hide(); }
bool visible() const { return this->visible(); }
protected:
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
Code:
#include <QtPlugin>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow
::changeEvent(QEvent *e
) {
switch (e->type()) {
ui->retranslateUi(this);
break;
default:
break;
}
}
Q_EXPORT_PLUGIN2(ui, MainWindow)
As you can see, main window is the code created by QtCreator and the interface IVisible has only two functions. My problem is there are errors while compiling:
undefined reference to `MainWindow::~MainWindow()'
undefined reference to `MainWindow::changeEvent(QEvent*)'
I think this is because I only add mainwindow.h to app.pro and Qt cannot find the cpp. But I should do this in order to create the main window in main() function. So how can I solve this problem? Must I create main window in application or create it in a function in the plugin and call it in main()?
Thank you!
Re: Plugin compiler error: undefined reference
if you call any methods of the type MainWindow this type's code is needed in your app;
if you cast plugin to IVisible instead, you might have more luck.
Re: Plugin compiler error: undefined reference
Quote:
Originally Posted by
caduel
if you call any methods of the type MainWindow this type's code is needed in your app;
if you cast plugin to IVisible instead, you might have more luck.
What I want to try to put all UI components into one dll so MainWindow is also in that dll. Then I should call this
MainWindow in main() function in order to show it. I checked the class name returned by QPluginLoader::instance()
and it was a MainWindow. I tried to cast it to IVisible using
Code:
IVisible * v = (IVisible *)plugin;
v->setVisible(true);
note that it is not a QObject so I cann't using qobject_cast but it also had the same problem. If I remove HEADERS += mainwindow.h
in app.pro, it is all right. But there is an runtime error when setVisible() called.
So how should I do? If I just want to get the MainWindow instance, how should I code? Or I can try IVisible but whatis the
runtime error?
Re: Plugin compiler error: undefined reference
Why you want your UI components to be a plugin? Can it be a regular library? You will get the .dll linked to your app.
The main idea of plugins is that there is defined one interface (an abstract C++ class) and you communicate with plugins trough that interface (that's why it is called interface...).
So in your case you should cast objects to IVisible and use only IVisible methods on loaded plugins (otherwise there are some methods in MainWindow declared in mainwindow.h but NOT IMPLEMENTED anywhere in your app...) or just get rid of this IVisible, make your plugin a regular library and link it to your app (like you already did).
But remember that in dll you need proper dllimport and dllexport -> create a new project "C++ library" in QtCreator to see how to deal with dll import and export (look at *_global.h, .pro file and class declaration).
Re: Plugin compiler error: undefined reference
Quote:
Originally Posted by
faldżip
Why you want your UI components to be a plugin? Can it be a regular library? You will get the .dll linked to your app.
The main idea of plugins is that there is defined one interface (an abstract C++ class) and you communicate with plugins trough that interface (that's why it is called interface...).
So in your case you should cast objects to IVisible and use only IVisible methods on loaded plugins (otherwise there are some methods in MainWindow declared in mainwindow.h but NOT IMPLEMENTED anywhere in your app...) or just get rid of this IVisible, make your plugin a regular library and link it to your app (like you already did).
But remember that in dll you need proper dllimport and dllexport -> create a new project "C++ library" in QtCreator to see how to deal with dll import and export (look at *_global.h, .pro file and class declaration).
Thank you! I also think I'm creating a shared library not a plugin. But I don't know how to import this library into my project? It says that I should use QLibrary. But the document only shows how to import functions from dll while I just export classes. Could you tell me how should I do if I've got the dll library by creating shared library project?
I just paste header file and dll file into the same file and add LIBS += -e:/works/test/ui.dll file. Then recompile this project there is no error but when I run it, the exit code is not 0 and no window shown. I don't know why?
Re: Plugin compiler error: undefined reference
This:
Code:
LIBS += -LE:\documents\test\app\plugins -lui
looks in E:\documents\test\app\plugins for ui.lib. And instead of copying mainwindow.h just add INCLUDEPATH += path/where/headers/are in app.pro file and remove it from HEADERS.
And show your ui.pro and mainwindow.h.
Re: Plugin compiler error: undefined reference
Hi! I tried to create a library instead of a plugin, so I had to modified existing code as following:
test.pro
Code:
# there is no any change
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += ui app
app.pro
Code:
TARGET = test
TEMPLATE = app
CONFIG += debug
SOURCES += main.cpp
LIBS += E:/documents/test/app/lib/ui.dll # I realized this is the correct syntax on Windows
INCLUDEPATH += ../ui
main.cpp
Code:
// Since this is a library, I think I should use it just like QtGui and so on, so I include necessary head files and create an instance as usual
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
MainWindow win;
win.show();
return a.exec();
}
ui.pro
Code:
# also I should edit this file in order to generate a library instead of a plugin
TARGET = ui
TEMPLATE = lib
DEFINES += UI_LIBRARY
CONFIG += debug
SOURCES += mainwindow.cpp
HEADERS += mainwindow.h \
ui_global.h
FORMS += mainwindow.ui
DESTDIR = ../app/lib
ui_global.h
Code:
#ifndef UI_GLOBAL_H
#define UI_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(UI_LIBRARY)
# define UISHARED_EXPORT Q_DECL_EXPORT
#else
# define UISHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // UI_GLOBAL_H
mainwindow.h
Code:
// OK, this is almost what QtCreator generated for me, I only added show() function in order to let Qt export this function, am I right?
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "ui_global.h"
namespace Ui {
class MainWindow;
}
class UISHARED_EXPORT MainWindow
: public QMainWindow { Q_OBJECT
public:
~MainWindow();
void show();
protected:
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
Code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow
::changeEvent(QEvent *e
) {
switch (e->type()) {
ui->retranslateUi(this);
break;
default:
break;
}
}
void MainWindow::show()
{
this->show();
}
OK, when I recompile this project, there is nothing wrong. But I could not run it. It says that "E:\documents\test\app\debug\test.exe exited with code -1073741819" although I have copied ui.dll to the same directory of test.exe.
Re: Plugin compiler error: undefined reference
Quote:
Originally Posted by
FinderCheng
app.pro
Code:
TARGET = test
TEMPLATE = app
CONFIG += debug
SOURCES += main.cpp
LIBS += E:/documents/test/app/lib/ui.dll # I realized this is the correct syntax on Windows
INCLUDEPATH += ../ui
I don't think so. Do you have ui.lib file generated with ui.dll. I'm not sure if DESTDIR works with it so check in debug folder. This ui.lib is the right file to link with while compiling and ui.dll it the right file to link with in runtime. And the previous syntax was okay - I use it on both - Windows and Linux.
Quote:
main.cpp
Code:
// Since this is a library, I think I should use it just like QtGui and so on, so I include necessary head files and create an instance as usual
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
MainWindow win;
win.show();
return a.exec();
}
That's correct.
Quote:
ui.pro
Code:
# also I should edit this file in order to generate a library instead of a plugin
TARGET = ui
TEMPLATE = lib
DEFINES += UI_LIBRARY
CONFIG += debug
SOURCES += mainwindow.cpp
HEADERS += mainwindow.h \
ui_global.h
FORMS += mainwindow.ui
DESTDIR = ../app/lib
This file looks okay now (for library).
Quote:
mainwindow.h
Code:
// OK, this is almost what QtCreator generated for me, I only added show() function in order to let Qt export this function, am I right?
No, it is already exported in QtGui.dll as it is part of QWidget class.
Quote:
OK, when I recompile this project, there is nothing wrong.
Are you sure? You are qmaking and building test.pro or app.pro?
Open VS command prompt, go to the app dir and run:
and see what you get.
Quote:
But I could not run it. It says that "E:\documents\test\app\debug\test.exe exited with code -1073741819" although I have copied ui.dll to the same directory of test.exe.
Use Dependency Walker to check library dependencies of your app.exe. And did you try also running it from outside of QtCreator just by double clicking test.exe?
Re: Plugin compiler error: undefined reference
Quote:
Originally Posted by
faldżip
I don't think so. Do you have ui.lib file generated with ui.dll. I'm not sure if DESTDIR works with it so check in debug folder. This ui.lib is the right file to link with while compiling and ui.dll it the right file to link with in runtime. And the previous syntax was okay - I use it on both - Windows and Linux.
Sorry, I check both DESTDIR and debug folders and there is no such file called ui.lib.
Quote:
Originally Posted by
faldżip
Are you sure? You are qmaking and building test.pro or app.pro?
Yes, I rebuild project with test.pro and app.pro each time and there is no error.
Quote:
Originally Posted by
faldżip
Open VS command prompt, go to the app dir and run:
and see what you get.
I'm sorry but I have no VS compiler. So I open app.pro as a separate project and build it, nothing wrong here.
Quote:
Originally Posted by
faldżip
Use Dependency Walker to check library dependencies of your app.exe. And did you try also running it from outside of QtCreator just by double clicking test.exe?
I have a little trouble with Dependency Walker. What results should I looking for? I checked test.exe(not app.exe, TARGET = test in app.pro) and its library contains ui.dll. And I tried to open test.exe outside QtCreator, no window opened...