Qt subdirs incude classes - c++

I'm follow Qt Echo Plugin example and trying to write complex application. My project have following structure:
MainDir \
Main.pro
kernel \
kernel.pro
abstractinterface.h
main.cpp
testplugin \
testplugin.pro
abstractplugin.h
abstractplugin.cpp
Problem is in plugin header file:
#include <QObject>
#include <QtPlugin>
#include "abstractinterface.h"
class AbstractPlugin : public QObject, AbstractInterface
// An error appears here
// expected class-name before '{' token
{
Q_OBJECT
//... plugin initialization code ...
public:
explicit AbstractPlugin(QObject *parent = 0);
};
Also, autocompletion can't find class AbstractInterface.
So, question is: what I'm doing wrong? In testplugin.pro file I have line INCLUDEPATH += ../kernel/.
Any help appreciated.
---- EDIT -----
abstractinterface.h
#include <QtPlugin>
#define INTERFACE_ID "AbstractInterface/1.0"
class AbstractInterface
{
public:
virtual ~AbstractInterface();
virtual void init();
virtual void enable();
virtual void disable();
};
Q_DECLARE_INTERFACE(AbstractInterface, INTERFACE_ID)

Given that your pasted files look correct and work here, I am leaning towards that your problem is this line:
INCLUDEPATH += ../kernel/
You likely execute qmake from the project root where your main project file resides calling qmake recursively to generate the Makefiles. However, at the point of generation, the aforementioned path will extend from the project root rather than from the sub-directory. Please fix your testplugin.pro project file by using this instead:
INCLUDEPATH += $$PWD/../kernel/
However, what is even better design is to not handle it inside that project file, but the other kernel.pro where the header files reside. It is more flexible design to add this in there:
INCLUDEPATH += $$PWD
Edit: Based on your comment which was not in the original question, it seems that you have another problem. You seem to have messed with the include guards called the same in two different files and that is why the second inclusion did not result in providing the accessibility for you.

Related

Qt Quick + CMake + custom QObject results in undefined reference to `vtable'

I use Qt Quick to make small application to work with files.
Everything was working until one moment i executed in my build/ folder
rm -rf *
cmake ..
make
And then make halted with this error (lising is huge, i suppresed non-important part):
[100%] Linking CXX executable uint32_sort_gui
In function `LibController::~LibController()':
lib_controller.cpp:(.text+0x10): undefined reference to `vtable for LibController'
main.cpp.o: In function `int qmlRegisterType<LibController>(char const*, int, int, char const*)':
...
Here is my .hpp and .cpp files of the class:
lib_controller.hpp
#include <QObject>
#include <QString>
class LibController : public QObject{
Q_OBJECT
Q_PROPERTY(decltype(getProgress) progress READ getProgress NOTIFY ProgressChanged)
public:
explicit LibController(QObject *parent = 0);
~LibController();
double getProgress();
Q_INVOKABLE
void addFile(QString from_name, QString to_name);
Q_INVOKABLE
void sortFile();
signals:
void ProgressChanged();
private:
double current_progress;
FileManager* file_manager;
};
lib_controller.cpp
#include "lib_controller.hpp"
LibController::~LibController(){
delete file_manager;
}
double LibController::getProgress(){...}
void LibController::addFile(QString from_name, QString to_name){...}
void LibController::sortFile(){...}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include "lib_controller.hpp"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
// Registration of custom type
qmlRegisterType<LibController>("com.sort.controller", 0, 1, "LibController");
...
return app.exec();
}
And my CMakeLists.txt configuration.
I read another questions about this problem, but cleaning and rebuilding did not help (i even accidentally deleted whole project folder).
The problem persists, and i do not understand, how to fix it ...
UPD:
Here is full error message
UPD2:
After excluded LibController from the project and recompiling it, error is gone, but no window is showed to me. I can see from terminal that it is running, but no GUI popped up.
I guess problem is not in LibController, but somewhere else.
You need to add headers to the list of your source files for cmake to be able to run AUTOMOC on them.
This question has been already asked and answered here Changing location of header file causes missing vtable error when compiling with CMake
Since you call out the constructor in your header try adding this to the cpp file:
LibController::LibController(QObject *parent) : QObject(parent) {
}
Also, I have found that Rebuild All doesn't re-run qmake all the time. If you still see the issue run Build, Run qmake to make sure the header is getting processed.
According to comments in this question, you should
Rename your custom object header file to moc_*your header name*.hpp
Add path to this header to add_executable() function
Clear build/ directory and rerun CMake
Be somewhat happy in the end of the day
Hope this will help somebody, who tried to find last resort, like me.

Qt shared_ptr not found when including a library

I'm using Qt creator and the yaml-cpp library. I placed yaml-cpp under my source code directory and added it to the Qt project's include path like so:
INCLUDEPATH += Crypto \
Yaml
QMAKE_CXXFLAGS += -std=gnu++0x
DEFINES += __GXX_EXPERIMENTAL_CXX0X__
As you can see, I also told it to use C++ 11 because that is a requirement of this library. However, I get this error on compiling my project (this is the only error):
../ProjectName/Yaml/yaml-cpp/node/ptr.h:11:10: fatal error: 'boost/shared_ptr.hpp' file not found
#include <boost/shared_ptr.hpp>
^
I also tried, at the advice of some online resources, to replace it with #include <memory>, but this does not work. When I try this, it still cannot find shared_ptr.
I probably could compile the library and link Qt creator to it, but I would have to do this on every platform I use and on every machine that every project developer uses. It seems like a more elegant solution to put the source code inside my GitHub directory and compile it along with the project to minimize the overhead of someone compiling the project on their machine, particularly since this is an open source project.
Here is the source code of Yaml-Cpp's file in question:
#include "yaml-cpp/dll.h"
#include <boost/shared_ptr.hpp>
namespace YAML
{
namespace detail {
class node;
class node_ref;
class node_data;
class memory;
class memory_holder;
typedef boost::shared_ptr<node> shared_node;
typedef boost::shared_ptr<node_ref> shared_node_ref;
typedef boost::shared_ptr<node_data> shared_node_data;
typedef boost::shared_ptr<memory_holder> shared_memory_holder;
typedef boost::shared_ptr<memory> shared_memory;
}
}
It seems that you do not have boost installed. You would need to amend that first.
However, you could urge the yaml-cop developers to use the recent C++ standard more and more when their software is built using C++11 or later. C++11 is not a new thing anymore. It should be utilized as much as possible.

Building a plugin to extend a Qt application

I decided to switch my hobby project application (a dictionary lookup program) to a plugin architecture to enable all kinds of different dictionaries to be developed for other languages in the future. The application is developed in Visual C++ with Qt (5.0.2). I added this header to the application code to define the interface for the dictionary plugins:
// dict_plugin.h
#ifndef DICT_PLUGIN_H
#define DICT_PLUGIN_H
#include <QtPlugin>
class PluginInterface
{
public:
virtual ~PluginInterface() {}
virtual QString language() const = 0;
virtual class QWidget* ui() const = 0;
};
Q_DECLARE_INTERFACE(PluginInterface, "pl.ksmvision.winona.PluginInterface")
#endif // DICT_PLUGIN_H
Next, I created a new project from the "Qt library" template for the plugin itself (using the Qt Visual Studio add-in) which is used to make dll's. The main header file looks like this:
#ifndef JP_PLUGIN_H
#define JP_PLUGIN_H
// created by the template to define Q_DECL_EXPORT
// and _IMPORT macros but the plugin engine takes
// care of that (I think)
//#include "jp_plugin_global.h"
#include <QObject>
#include <QtPlugin>
#include <dict_plugin.h>
class JpPlugin : public QObject, public PluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "pl.ksmvision.winona.JpPlugin")
Q_INTERFACES(PluginInterface)
public:
JpPlugin();
virtual ~JpPlugin();
virtual QString language() const;
virtual QWidget* ui() const;
};
#endif // JP_PLUGIN_H
When I try to build this, I get an error from moc on the Q_INTERFACES line specifying the interfaces my plugin is supposed to be implementing:
3>------ Build started: Project: jp_plugin, Configuration: Debug Win32 ------
3> Moc'ing jp_plugin.h...
3>F:\moje\src\cpp\winona\build\jp_plugin\jp_plugin.h(15): error : Undefined interface
========== Build: 2 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
It looks like moc'ing takes place before the dict_plugin.h file is included, because when I introduce a typo to the include filename, it doesn't complain that the file doesn't exist, just terminates the build with that same error message about the interface being undefined.
What am I doing wrong? Thanks.
The reason moc failed was because the interface declaration was unavailable. The #include directive failed because the file could not be found. Apparently, moc can process #include directives by itself, but doesn't (by default?) print an error message or halt processing if the file to be included can't be found.
The reason the header file with the interface declaration could not be found is that the custom build settings which cause moc to be invoked that are generated by the Qt VS add-in don't inherit the project's include path. I managed to add the required path manualy to moc's command line by entering the property pages of the plugin's header file, browsing to Custom Build Tool->General->Command Line and adding an extra "-I..." include option at the end. After that, moc processed the header and the build was successfull.
For those who venture down this path like I did. My issue was slightly different and had to do with namespaces. I was getting the exact same "undefined interface" error, but the path resolution had no effect for me.
I had something like the following:
namespace foo {
class Interface
{
// ...
};
} // namespace foo
Q_DECLARE_INTERFACE(foo::Interface, "my.interface/1.0")
Incorrect
namespace foo {
class Derived : public QObject, public Interface
{
Q_OBJECT
Q_INTERFACES(Interface)
};
}
Correct
namespace foo {
class Derived : public QObject, public Interface
{
Q_OBJECT
Q_INTERFACES(foo::Interface) //!< Notice foo:: is still provided
};
}
Reason
From the documentation:
If you want to use Q_DECLARE_INTERFACE with interface classes declared in a namespace then you have to make sure the Q_DECLARE_INTERFACE is not inside a namespace though.
But what they don't mention is that the Q_INTERFACES(), even when inside of that namespace by scope, still requires the namespace be provided as though it were global.

Using Dlls in Qt C++

I'm trying to build a project with a library (dll) I made. I've never attempted to either load or make a library before and I'm getting the following error.
error: undefined reference to `imp__ZN6NeuronC1Ev'
In Qt, the error is shown in the following line.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) <--------------------------- Error indicated here.
{
ui->setupUi(this);
}
Project File
QT += core gui
TARGET = Jane
TEMPLATE = app
LIBS += -L quote(C:\Programming\Jane\Jane\Source\Neuron.dll)
SOURCES += main.cpp\
MainWindow.cpp
HEADERS += MainWindow.h
FORMS += MainWindow.ui
Here is one of the classes that I've exported
#ifndef NEURON_H
#define NEURON_H
#include <QList>
#include "Neuron_global.h"
#include <Sensor.h>
class NEURONSHARED_EXPORT Neuron
{
public:
explicit Neuron();
const double getOutput() const;
const double & getWeight() const;
void setWeight(const double& weight);
private:
double weight; // The weight of this neuron.
QList<Neuron*> neurons; // This Neuron's children.
QList<Sensor*> sensors; // This Neuron's Sensors.
};
#endif // NEURON_H
The NEURONSHARED_EXPORT Marco is defined in "Neuron_global.h"
#ifndef NEURON_GLOBAL_H
#define NEURON_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(NEURON_LIBRARY)
# define NEURONSHARED_EXPORT Q_DECL_EXPORT
#else
# define NEURONSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // NEURON_GLOBAL_H
If anyone has any advice on how to fix this, I would greatly appreciate it.
Edit:
I've added the libNeuron.a file to the LIBS argument in pro file. However, I'm now getting the following error.
LIBS += libNeuron.a
cannot find -lNeuron.a
any ideas?
What are you trying to do?
LIBS += -L quote(C:\Programming\Jane\Jane\Source\Neuron.dll)
It variable contains a lib-files, which project will be linked with, not a library itself!
You should find a lib for the dll or use WINAPI LoadLibrary/GetProcAddres functions to load dll dynamically.
This is only a quick guess of mine: your trouble is caused c++ name mangling. Google
"qt dll c++ name mangling"
and find some examples of working dll / client projects.
In this case everything looks right (assuming NEURON_LIBRARY is not defined since you're building under the app template, although Windows v. Linux act differently in this regard).
qmake is known not to pick up all the changes that it ought to so I'd recommend re-running qmake and then your make variant (e.g. make, gmake, nmake):
$ qmake
$ nmake
In some cases, you'll actually need to do a clean (or delete the relevant object files) before everything will be able to link correctly.

C++ Qt Multiple Definitions

I'm trying to create a simple GUI application (so far) in Qt with C++ using the MinGW compiler. However, the compiler is informing me that I have a multiple definition of 'WiimoteScouter::WiimoteScouter(QWidget*)' on line 4 of wiimotescouter.cpp. I am using a check to make sure the header isn't included multiple times, but apparently it's not working, and I'm not sure why.
Here's the header file:
#ifndef WIIMOTESCOUTER_H
#define WIIMOTESCOUTER_H
#include <QWidget>
class QLabel;
class QLineEdit;
class QTextEdit;
class WiimoteScouter : public QWidget
{
Q_OBJECT
public:
WiimoteScouter(QWidget *parent = 0);
private:
QLineEdit *eventLine;
};
#endif // WIIMOTESCOUTER_H
And here's the cpp file:
#include <QtGui>
#include "wiimotescouter.h"
WiimoteScouter::WiimoteScouter(QWidget *parent) :
QWidget(parent)
{
QLabel *eventLabel = new QLabel(tr("Event:"));
eventLine = new QLineEdit;
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(eventLabel, 0, 0);
mainLayout->addWidget(eventLine, 0, 1);
setLayout(mainLayout);
setWindowTitle(tr("Wiimote Alliance Scouter"));
}
Lastly, the main.cpp:
#include <QtGui>
#include "wiimotescouter.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
WiimoteScouter wiimoteScouter;
wiimoteScouter.show();
return app.exec();
}
I've seen this happen before when a source file got duplicated in the project (.pro or .pri) file. Check all of the "SOURCES =" and "SOURCES +=" lines in your project file and make sure the cpp file is not in there more than once.
I don't use MinGW but this sounds like a linker error rather than a compiler error. If this is the case then you should check that the .CPP file is not added to the project twice. I also noticed that the extension is "php", this is very unusual as it should be "cpp".
Answer just for reference:
I was including
#include myclass.cpp
instead of
#include myclass.h
This can also happen if you have two .ui files with the same name in different folders. Their corresponding headers are built in the same directory, resulting in one being overwritten. At least that was my problem.
I got this error message when I had my slot declarations listed listed under the signals heading in the header file, rather than the slots one. Another thing for anyone experiencing this error message to check for.
Cut and paste solved the problem and a need to check next time I create Slots manually.
For me it was due to Qt's compilation model in Windows using MinGW.
My code compiled perfectly fine for Linux, but for Windows the linker errors were happening for following files:
Message.cpp
Util.cpp
At first, in the .pro file, I couldn't find any similar file names. Then observing keenly I figured out that, the external google protobuf library, which I was compiling along, had some library files inside its folder named as:
message.cc
util.cc
The cases and the extensions were different, but somehow it created mess in the Qt compilation. I just added an underscore to those library files and the things worked fine.
In my case this was caused by having the function declared globally in a header file.