I have raw (no QtDesigner) Qt5 project with two simple plugins, which one don't load with laconic error: "plugin verification data mismatch".
Header of first plugin (which loads and run well):
#ifndef __PIROGRONIAN__P2P2__GUI_PLUGIN__H__
#define __PIROGRONIAN__P2P2__GUI_PLUGIN__H__
#include "QtCore/QtCore"
#include "PluginInterface.h"
namespace P2P2 {
class GuiPlugin : public QObject, public PluginInterface {
Q_OBJECT
Q_PLUGIN_METADATA(IID "Pirogronian.P2P2.GuiPlugin")
Q_INTERFACES(P2P2::PluginInterface)
public:
bool init(CoreServer *);
bool receiveObject(Object*);
int channelType();
};
};
#endif
The second one, which don't load:
#ifndef __PIROGRONIAN__P2P2__CHAT_PLUGIN__H__
#define __PIROGRONIAN__P2P2__CHAT_PLUGIN__H__
#include <QtNetwork/QtNetwork>
#include "Chat.h"
#include "PluginInterface.h"
namespace P2P2 {
class ChatPlugin : public QObject, public PluginInterface {
Q_OBJECT
Q_PLUGIN_METADATA(IID "Pirogronian.P2P2.ChatPlugin")
Q_INTERFACES(P2P2::PluginInterface)
CoreServer *_server;
QHash<Channel *, Chat *> _chats;
public:
virtual bool init(CoreServer *);
virtual bool receiveObject(Object *);
virtual int channelType();
};
};
//Q_DECLARE_METATYPE(QPointer<P2P2::ChatPlugin>)
#endif
Here is PluginInterface header:
#ifndef __PIROGRONIAN__P2P2__PLUGIN_INTERFACE__H__
#define __PIROGRONIAN__P2P2__PLUGIN_INTERFACE__H__
#include "CoreServer.h"
namespace P2P2 {
class PluginInterface {
public:
virtual bool init(CoreServer *) = 0;
virtual bool receiveObject(Object *) = 0;
virtual int channelType() = 0;
};
};
Q_DECLARE_INTERFACE(P2P2::PluginInterface, "Pirogronian/P2P2/PluginInterface/1.0")
#endif
I'm not expert and writing plugins for qt5 is described very cursorily. But since I can't find any major difference between those plugins, problem becomes rather mysterious to me. Mayby a bug in Qt? I've rebuilt both several times to bye sure that both are up to date.
I'm trying put the whole code somewhere into net, but it'll take a while... Edit: done - packed as zip here: http://uploaduj.net/D74c2f/v0-1-pure-zip/
Not sure if it helps but it seems that your plugin has invalid metadata. Here's code that sets error message http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/plugin/qlibrary.cpp#n303
You could use debug version of Qt and set breakpoint in that function. This would give you exact line that fails while loading your plugin.
Maybe you have an error in your metadata?
Related
Aaand im back again with my second question and im kinda not sure about wether i should have posted all the seperate classes cuz it looks somewhat long. And im sure the solution is pretty small.
Anyways, i am at polymorphism tutorial vid that i am following and everything works fine if i follow it and put all classes in "main.cpp". But when i tried to do the same program with seperate classes (seen below) i am getting error "
E:\Codeblocks\Poly\main.cpp|11|error: cannot convert 'Ninja' to 'Enemy*' in initialization|".*
I kinda understand what the error is saying..i think.. but dont know what i did wrong since the same code was working when Enemy and Ninja class wasnt seperate but now as seperate classes its not working. I think i included those classes properly in main.cpp.
main.cpp
#include <iostream>
#include "Enemy.h"
#include "Ninja.h"
#include "Monster.h"
int main()
{
Ninja n;
Monster m;
Enemy *enemy1=&n;
Enemy *enemy2=&m;
enemy1->setAttackPower(20);
enemy2->setAttackPower(50);
n.attack();
m.attack();
return 0;
}
Enemy.h
#ifndef ENEMY_H
#define ENEMY_H
class Enemy
{
public:
Enemy();
void setAttackPower(int a);
protected:
int attackPower;
private:
};
#endif // ENEMY_H
Enemy.cpp
#include "Enemy.h"
Enemy::Enemy()
{
//ctor
}
void Enemy::setAttackPower(int a)
{
attackPower=a;
};
Ninja.h
#ifndef NINJA_H
#define NINJA_H
class Ninja
{
public:
Ninja();
void attack();
protected:
private:
};
#endif // NINJA_H
Ninja.cpp
#include "Ninja.h"
#include <iostream>
Ninja::Ninja()
{
//ctor
}
void Ninja::attack(){
std::cout<<" I am a ninja. Ninja chop! -"<<attackPower<<"\n";}
This is because your Ninja class is not inhereted from Enemy class. You must define Ninja class like this:
#include "Enemy.h"
class Ninja : public Enemy
{
public:
Ninja();
void attack();
protected:
private:
};
EDIT: I added #include directive. Without it compiler won't know, where to find Enemy class declaration.
In a Qt application I declare a base class:
class Base:
public QObject {
Q_OBJECT
public:
Base();
virtual ~Base();
virtual void doSomething();
};
Both the c-tor/d-tor and doSomething() have default implementations in a separate source file.
Furthermore, I provide an abstract interface to implement Qt's plugin scheme, like in the Echo Plugin Example.
class Interface {
public:
virtual ~Interface() {}
virtual Base *create() = 0;
};
#define Interface_iid "blag"
Q_DECLARE_INTERFACE(Interface, Interface_iid)
In a plugin that resides in a shared library, libPlugin.so I derive from this base class to provide custom implementations:
class Special:
public Base {
Q_OBJECT
public:
Special() { /* Implementation */ }
void doSomething() { /* Implementation */ }
};
Finally I also implement the plugin interface:
class Q_DECL_EXPORT Plugin:
public QObject,
public Interface {
Q_OBJECT
Q_PLUGIN_METADATA(IID Interface_iid)
Q_INTERFACES(Interface)
public:
Base *create() {
return new Special();
}
};
Now I can load this plugin via QPluginLoader and obtain access to its core object, which correctly identifies itself being a Plugin. But when I try to ThePlugin::create() the Special object, I get a linkage error:
symbol lookup error: libPlugin.so: undefined symbol: _ZN4BaseC2Ev
Beneath the name mangling, I suppose this refers to the Base::Base c-tor that is needed when constructing the derived Special object.
I'm tempted to compare to, e.g. a QStylePlugin: It basically does the same, returning some QStyle-derived class via an abstract interface. Please refer to the Style Plugin Example. Yet I guess the difference is that in the case of the style plugin, both the application (that provides the custom style plugin) and the style plugin itself are linked against the common Qt library that provides, e.g. the c-tors.
How could I resolve this?
What happens if link time optimization removes the c-tors because it cannot know they're needed by plugins?
Linking issue
When compiling and linking the plugin, the Base:Base() class' c-tor as well as the Base::doSomething() come out as unresolved symbol. The c-tor is called by the Special::Special() c-tor and cannot be resolved, of course. The other one is a virtual method
When compiling the application itself, it contains the implementations of the base class' methods. Obviously, they are not linked together when the plugin is loaded.
SSCCE
/********** Interface.h */
#ifndef INTERFACE_H
#define INTERFACE_H
#include <QtPlugin>
#include "Base.h"
class Interface {
public:
virtual ~Interface() { }
virtual Base *createWorker() = 0;
};
#define Interface_iid "blag"
Q_DECLARE_INTERFACE(Interface, Interface_iid)
#endif
/********** App.pro */
QT += core
TARGET = App
TEMPLATE = app
SOURCES += \
Base.cpp \
App.cpp
HEADERS += \
Base.h \
Interface.h \
/********** Base.h */
#ifndef BASE_H
#define BASE_H
#include <QObject>
class Base:
public QObject {
Q_OBJECT
public:
Base();
virtual ~Base();
virtual void doSomething();
};
#endif
/********** Base.cpp */
#include "Base.h"
Base::Base():
QObject() {
}
Base::~Base() { }
void Base::doSomething() { }
/********** App.cpp */
#include "Interface.h"
#include <QCoreApplication>
#include <QPluginLoader>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QPluginLoader l("libPlugin.so");
qDebug() << l.load();
qDebug() << l.errorString();
return a.exec();
}
/********** Plugin.pro */
TARGET = Plugin
CONFIG += plugin
TEMPLATE = lib
SOURCES += \
Plugin.cpp \
Special.cpp \
HEADERS += \
Plugin.h \
Special.h \
Interface.h \
Base.h
/********** Special.h */
#ifndef SPECIAL_H
#define SPECIAL_H
#include <QObject>
#include "Base.h"
class Special:
public Base {
Q_OBJECT
public:
Special();
void doSomething();
};
#endif
/********** Special.cpp */
#include "Special.h"
Special::Special():
Base() {
}
void Special::doSomething() { }
/********** Plugin.h */
#ifndef PLUGIN_H
#define PLUGIN_H
#include <QObject>
#include "Interface.h"
class Q_DECL_EXPORT Plugin:
public QObject,
public Interface {
Q_OBJECT
Q_PLUGIN_METADATA(IID Interface_iid)
Q_INTERFACES(Interface)
public:
Base *createWorker();
};
#endif
/********** Plugin.cpp */
#include "Plugin.h"
#include "Special.h"
Base *Plugin::createWorker() {
return new Special();
}
Build:
# Separate files
qmake Plugin.pro && make
qmake App.pro && make
./App
I think I found what is wrong.
The construction I'd like to have linked is as follows:
A host application providing a base class with implementations
A plugin shared library that inherits from that base and re-implements some methods and/or accesses the base class' members
This basically boils down to the following in plain C:
A host application, providing some symbols
A plugin shared library, providing some more symbols and wanting to use some of the host's symbols
However, there is no generic way to achieve the latter.
A host can link against a library to use its functionality. That means the host gets method stubs that are dynamically resolved into against library once the host itself and the library are loaded. Contract between library and host may be some header file with declarations (not definitions).
When a library is dynamically loaded into a host's memory, symbols in the library in turn are not resolved against the host, though. Instead they stay unresolved.
This is exactly what I am seeing here. I tried to resolve the base class' functionality (that I did not implement in the plugin) against the host application that wants to load the plugin. Does-not-work.
This is that -rdynamic is for on ELF, refer to this post.
I have two classes: AbstractClass and SubClass.
This is basically my code (well, just some example code):
abstractclass.h
class AbstractClass
{
public:
AbstractClass();
void doSomething();
protected:
virtual void implementMe() = 0;
int a;
};
abstractclass.cpp
#include "abstractclass.h"
AbstractClass::AbstractClass(){}
void AbstractClass::doSomething()
{
implementMe(); // compiler error: "implementMe() was not declared in this scope"
a = 0; // same compiler error here...
}
subclass.h
#include "abstractclass.h"
class SubClass : public AbstractClass
{
public:
SubClass();
protected:
void implementMe();
};
subclass.cpp
#include "subclass.h"
SubClass::SubClass() {}
void SubClass::implementMe()
{
// do some stuff
}
In the AbstractClass, however, I keep getting a compiler error (for the virtual function as well as for the class variable):
implementMe() was not declared in this scope
The only way I found to get rid of this was to use forward-declaration:
void implementMe();
AbstractClass::doSomething()
{
implementMe();
}
I cannot believe that this is the correct way, though?
Thanks!
EDIT:
Ok, as my conceptual understanding of subclassing in C++ doesn't seem to be totally wrong (see the comments), I'm gonna share some of my original source code. Hopefully this will help to indentify the error.
This is my abstract / base class:
abstractenvironment.h
#ifndef ABSTRACTENVIRONMENT_H
#define ABSTRACTENVIRONMENT_H
#include <QObject>
class AbstractEnvironment : public QObject
{
Q_OBJECT
public:
AbstractEnvironment(QObject *parent = 0);
protected:
virtual void process() = 0;
quint32 counter;
private slots:
void handleTimeout();
};
#endif // ABSTRACTENVIRONMENT_H
abstractenvironment.cpp
#include "abstractenvironment.h"
#include <QTimer>
QTimer *myTimer;
AbstractEnvironment::AbstractEnvironment(QObject *parent) :
QObject(parent)
{
myTimer = new QTimer(this);
connect(myTimer, &QTimer::timeout, this, &AbstractEnvironment::handleTimeout);
myTimer->start(1);
counter = 0;
}
void handleTimeout()
{
process();
counter++;
}
And this is my subclass:
environment.h
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
#include "abstractenvironment.h"
class Environment : public AbstractEnvironment
{
Q_OBJECT
public:
Environment(Controller *controller, QObject *parent = 0);
protected:
void process();
};
#endif // ENVIRONMENT_H
environment.cpp
#include "environment.h"
Environment::Environment(Controller *controller, QObject *parent) :
AbstractEnvironment(controller, parent) {}
void Environment::process()
{
// do something
}
PS: I've learned from the first part of this question and tried to compile the source code above inside Qt with MinGW. I get exactly two error messages (as expected):
..\untitled\abstractenvironment.cpp: In function 'void handleTimeout()':
..\untitled\abstractenvironment.cpp:17:13: error: 'process' was not declared in this scope
..\untitled\abstractenvironment.cpp:18:5: error: 'counter' was not declared in this scope
In case you want to try it yourself, I've zipped the Qt project and uploaded it to my Dropbox (of course I will remove this file at some point but the code is exactly the same as in the post above --> it's just for the sake of convenience, so you don't have to copy-paste it yourself)
EDIT: You just changed your question. So I can't tell if your original text was your actual source code or not. Good rule of thumb, paste your actual code rather than paraphrase it (then de-identify or reduce it if needed).
ORIGINAL ANSWER:
implementMe(); // compiler error: "implementMe() was not declared in this scope"
That is because doSomething() isn't declared properly in AbstractClass. You "declared" it in the base class with:
doSomething();
The compiler doesn't recognize AbstractClass::doSomething() out of line definition so nothing inside the implementation is resolved to the class scope.
Change that to:
void doSomething();
just like in your derived class.
and
AbstractClass::doSomething()
{
implementMe();
}
to
void AbstractClass::doSomething()
{
implementMe();
}
UPDATE:
void handleTimeout()
{
process();
counter++;
}
is a global function. That isn't the class implementation. It should be:
void AbstractClass::handleTimeout()
{
process();
counter++;
}
In abstractenvironment.cpp you define void handleTimeout(), which is non-member function and does not relate to AbstractEnvironment class. Thus, it doesn't look for AbstractEnvironment::process() and AbstractEnvironment::counter, but for ::process() and ::counter instead (which are not declared, hence the error).
Change it to void AbstractEnvironment::handleTimeout() and it should compile.
So I have been having this extremely frustrating problem lately with Visual C++ 2012. Up until a few hours ago, I was writing code just fine and everything was working as intended, until I decided to optimize some things and deleted a few classes. I fixed all of the errors that were popping up because of that, e.g. false includes, etc. Unfortunately, after this the VS compiler went crazy. It started giving me errors such as:
Error 14 error C2653: 'Class' : is not a class or namespace name
or even
Error 5 error C2143: syntax error : missing ';' before '}'
Error 4 error C2059: syntax error : '>'
I've checked multiple times, and everything is in it's right place: all headers included, all symbols placed where they should be.
As far as I understand, the problem is not with my code but with the compiler itself... Visual Studio can be really annoying at times, I guess. Anyway, I would really be grateful if someone could help me out on this one.
(By the way, disabling precompiled headers did not work)
Relevant parts of code:
Error 14:
#include "PlayerEntity.h"
PlayerEntity::PlayerEntity(void) {} // This line causes the error
Error 5:
class GameScreen : public BaseScreen
{
public:
...
private:
...
}; // This line causes the error
Error 4:
private:
std::vector<BaseEntity*> _EntityList; // This line causes the error
Whole PlayerEntity.h file:
#ifndef PENTITY_H
#define PENTITY_H
#include "BaseEntity.h"
class PlayerEntity : public BaseEntity
{
public:
PlayerEntity(void);
PlayerEntity(float, float);
virtual ~PlayerEntity(void);
void render(sf::RenderWindow&);
void update();
private:
void init();
};
#endif
Whole GameScreen.h file:
#ifndef GSCREEN_H
#define GSCREEN_H
#include "BaseScreen.h"
#include "BaseEntity.h"
#include "PlayerEntity.h"
class GameScreen : public BaseScreen
{
public:
GameScreen(sf::Vector2u&);
virtual ~GameScreen(void);
void start();
void stop();
void render(sf::RenderWindow&);
void update(void);
void addEntity(BaseEntity*);
void destoryEntity(int id);
private:
std::vector<BaseEntity*> _EntityList;
sf::Vector2u _ScreenDimensions;
};
#endif
Whole BaseEntity.h file:
#ifndef BSENTITY_H
#define BSENTITY_H
#include "Input.h"
#include <SFML/Graphics.hpp>
class BaseEntity
{
public:
BaseEntity(void);
virtual ~BaseEntity(void);
sf::Vector2f position;
virtual void update(void);
virtual void render(sf::RenderWindow&);
void compare(BaseEntity*);
protected:
sf::Texture *_EntityTexture;
sf::Sprite _EntitySprite;
bool _isAlive;
int _id;
virtual void init();
};
#endif
Whole Input.h file:
#ifndef INPUT_H
#define INPUT_H
#include "ScreenSystem.h"
#include <SFML/Window.hpp>
class Input
{
public:
Input(void);
Input(sf::RenderWindow*);
virtual ~Input(void);
static bool keyPressed(int);
static bool keyReleased(int);
static bool mouseHeld(int);
static bool mouseReleased(int);
private:
static sf::RenderWindow *_Window;
};
#endif
Whole ScreenSystem.h file:
#ifndef GHANDLER_H
#define GHANDLER_H
#include "BaseScreen.h"
#include "MenuScreen.h"
#include "GameScreen.h"
#include <SFML/Window.hpp>
class ScreenSystem
{
public:
ScreenSystem(void);
ScreenSystem(sf::RenderWindow*);
virtual ~ScreenSystem(void);
BaseScreen *getCurrentScreen(void);
void setScreen(int);
private:
int _currentScreenID;
std::vector<BaseScreen*> _Screens;
sf::RenderWindow *_Window;
};
#endif
You have a circular dependency in your headers. BaseEntity.h includes Input.h, which includes ScreenSystem.h, which includes GameScreen.h, which in turn re-includes BaseEntity.h. This leads to class names appearing before they are declared, causing compilation failure.
To avoid this, do not include headers unnecessarily. For example, do not include Input.h from BaseEntity.h, since it's not needed at all; and do not include BaseScreen.h from ScreenSystem.h since only a declaration class BaseScreen; is needed, not the complete class definition.
Also, check that you do not have duplicate header guards. Some of them do not match the header name (e.g. GHANDLER_H for ScreenSystem.h), which makes me think that they may have been accidentally copied from other headers. Finally, don't use reserved names like _EntitySprite for your own symbols; for simplicity, avoid leading or double underscores.
Did you copy the error messages into your question or did you retype them? Because error 14 has 'Class' with a capital C which is almost certainly not right.
Also, you should use as few include directives in your header files as possible. For example, GameScreen doesn't use PlayerEntity, so you can remove that include and BaseEntity is only used via pointer so you can replace
#include "BaseEntity.h"
with a forward declaration
class BaseEntity;
I don't know why I'm getting this error, because it compiled perfectly just an hour ago and I haven't made any change here.
I have a class called SocketsStatus, and then I have many threads which implement a socket connection each one. So I'm passing a reference to a SocketsStatus object to control which ones are connected and which ones not.
Header of SocketsStatus:
#ifndef SOCKETSSTATUS_H_
#define SOCKETSSTATUS_H_
#include <QMutex>
#include <BufferDatos.h>
class SocketsStatus {
public:
SocketsStatus();
int setBufferStatus(int bufferId, bool status);
bool isEveryBufferDisconnected();
virtual ~SocketsStatus();
private:
void init();
bool bufferRawMeasConnected;
bool bufferPosConnected;
bool bufferRtkConnected;
QMutex *mutex;
};
#endif /* SOCKETSSTATUS_H_ */
Then, beginning of header of BufferDatos, which is my Thread class:
#ifndef BUFFERDATOS_H_
#define BUFFERDATOS_H_
#include <QThread>
#include <QTcpSocket>
#include <SocketsStatus.h>
#include "Global.h"
class BufferDatos: public QThread {
public:
BufferDatos(QString ip, qint16 port, SocketsStatus &buffersStatusPassed);
virtual QByteArray extraerSiguienteMensaje(void) = 0;
virtual ~BufferDatos();
protected:
void run(void);
bool connect(void);
void receiveData(void);
bool reconnect(int &timeoutsWithOpenSocket);
protected:
QTcpSocket *tcpSocket;
QString ip;
qint16 port;
SocketsStatus &buffersStatus;
//...
I'm getting error: ‘SocketsStatus’ has not been declared at the ctr, and then when declaring the variable as protected I also get error: ‘SocketsStatus’ does not name a type.
Must be some stupid detail, but I don't happen to see where! Any help?
You have an #include cyclic dependency. Each of your header tries to include the other one. Does SocketsStatus really need to know about BufferDatos? You need to remove one of the two #includes, you may replace one of them with a forward declaration.
break your cyclic #include dependency (by omitting one of the #include directives) and replace it with a (or few) forward declarations.
In fact, I don't think you need to #include <Bufferdatos.h> in the first header.