Started using QtRO and generated files inherently complain about vtable:
#ifndef REP_REMOTEEXAMPLE_H
#define REP_REMOTEEXAMPLE_H
// This is an autogenerated file.
// Do not edit this file, any changes made will be lost the next time it is generated.
#include <QtCore/qobject.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qvariant.h>
#include <QtCore/qmetatype.h>
#include <QtRemoteObjects/qremoteobjectnode.h>
#include <QtRemoteObjects/qremoteobjectpendingcall.h>
#include <QtRemoteObjects/qremoteobjectreplica.h>
class remoteExampleReplica : public QRemoteObjectReplica
{
Q_OBJECT
Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_TYPE, "remoteExample")
Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_SIGNATURE, "5e40a606abdd95f709878d419edaa735fce25d0d")
public:
remoteExampleReplica() : QRemoteObjectReplica() { initialize(); }
static void registerMetatypes()
{
static bool initialized = false;
if (initialized)
return;
initialized = true;
}
private:
remoteExampleReplica(QRemoteObjectNode *node, const QString &name = QString())
: QRemoteObjectReplica(ConstructWithNode)
{
initializeNode(node, name);
}
void initialize() override
{
remoteExampleReplica::registerMetatypes();
QVariantList properties;
properties.reserve(0);
setProperties(properties);
}
public:
virtual ~remoteExampleReplica() {}
Q_SIGNALS:
void Close(QString a);
void Open(QString b);
public Q_SLOTS:
void onClosed()
{
static int __repc_index = remoteExampleReplica::staticMetaObject.indexOfSlot("onClosed()");
QVariantList __repc_args;
send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);
}
void onOpened()
{
static int __repc_index = remoteExampleReplica::staticMetaObject.indexOfSlot("onOpened()");
QVariantList __repc_args;
send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);
}
private:
friend class QT_PREPEND_NAMESPACE(QRemoteObjectNode);
};
#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))
#endif
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
#endif // REP_REMOTEEXAMPLE_H
The issue points to the private constructor. I only included the replica header in my code without really using the remote object as a test run. I've read a lot about vtables how they work and when the linker complains about the vtable but in this case, with the private constructor, I'm not sure what the issue is. Am I missing an implementation of the remote object? Did I not generate the files correctly?
.rep:
class remoteExample
{
SIGNAL(Close(QString a));
SIGNAL(Open(QString b));
SLOT(onClosed());
SLOT(onOpened());
};
Related
I'm working at a socket class for my application that will introduce me in QT framework. When I try to build I get this error: 'this' is unavailable for static member functions.
This is my class .h and .cpp
#pragma once
#include <QObject>
class QTcpSocket;
namespace Ps{
class InstSocket : public QObject
{
Q_OBJECT
public:
InstSocket(QObject *parent=0);
bool Connect();
bool isOpen();
void Disconnect();
//Geters
QString GetHostName() const {return m_hostName;}
quint16 GetPort() const {return m_port;}
//seters
void SetHostName(const QString& value);
void SetPort(quint16 value);
void SetLongWaitMs(int value){m_longWaitMs = value;}
void SetShortWaitMs(int value){m_shortWaitMs = value;}
void WriteData(const QString &data) const;
~InstSocket();
QString ReadData() const;
signals:
static void NotifyConnected();
static void NotifyDisconnected();
private slots:
void onConnected();
void onDisconnected();
private:
//this holds a reference to QtcpSocket
QTcpSocket& m_socket;
QString m_hostName;
quint16 m_port;
int m_shortWaitMs;
int m_longWaitMs;
explicit InstSocket(const InstSocket& rhs) = delete;
InstSocket& operator= (const InstSocket& rhs) = delete;
};
}
and the cpp:
#include "instsocket.h"
#include "QTcpSocket"
#include "QDebug"
#include "utils.h"
namespace Ps
{
InstSocket::InstSocket(QObject *parent) :
QObject(parent),
m_socket(*new QTcpSocket(this)),
m_hostName(""),
m_port(0),
m_shortWaitMs(0),
m_longWaitMs(0)
{
/* my signals are wired to the undelying socket signals, the signal connected is triggered, when a conection
* is established. This will be wired to onConnected and Disconnected slots*/
connect(&m_socket, &QTcpSocket::connected, this, &InstSocket::onConnected);
connect(&m_socket, &QTcpSocket::disconnected, this, &InstSocket::onDisconnected);
}
bool InstSocket::Connect()
{
qDebug() << "attempting to connect to "<< m_hostName << "on port" << m_port << "with wait time: "<<m_longWaitMs;
m_socket.connectToHost(m_hostName, m_port, QTcpSocket::ReadWrite);
return m_socket.waitForConnected(m_longWaitMs);
}
bool InstSocket::isOpen()
{
return m_socket.isOpen();
}
void InstSocket::Disconnect()
{
if(!isOpen()) return;
m_socket.disconnectFromHost();
}
void InstSocket::onConnected()
{
emit NotifyConnected();
}
void InstSocket::onDisconnected()
{
emit NotifyDisconnected();
}
void InstSocket::SetHostName(const QString &value)
{
m_hostName = value;
}
void InstSocket::SetPort(quint16 value)
{
m_port = value;
}
void InstSocket::WriteData(const QString &data) const
{
/*support for writeing to socket. The write metod of the socket will return the number of bites writen*/
int bytes_written = m_socket.write(qPrintable(data));
qDebug() << "Bytes written: "<<bytes_written;
}
QString InstSocket::ReadData() const
{
if(!m_socket.isReadable())
{
return "ERROR: Socket is unreadable.";
}
QString result;
//until the socket reports there is no data available
while(!m_socket.atEnd())
{
result.append(m_socket.readAll());
/*since typically a PC would be much faster at reading than an instrument might be at writing
* instrument must have a chance to queue up more data in case the message it's sending us is long.*/
m_socket.waitForReadyRead(m_shortWaitMs);
}
return result;
}
InstSocket::~InstSocket()
{
Utils::DestructorMsg(this);
}
}
and this is the error:
Qt Projects\build-Vfp-Desktop_Qt_5_7_0_MSVC2015_64bit-Debug\debug\moc_instsocket.cpp:-1: In static member function 'static void Ps::InstSocket::NotifyConnected()':
error: 'this' is unavailable for static member functions
QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR); In static member function 'static void Ps::InstSocket::NotifyDisconnected()':
error: 'this' is unavailable for static member functions
QMetaObject::activate(this, &staticMetaObject, 1, Q_NULLPTR);
When I clicked on them, QT creator took me to moc_instsocket.cpp (that is in build folder and poit to this:
// SIGNAL 0
void Ps::InstSocket::NotifyConnected()
{
QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR);
}
// SIGNAL 1
void Ps::InstSocket::NotifyDisconnected()
{
QMetaObject::activate(this, &staticMetaObject, 1, Q_NULLPTR);
}
I can't figure out what to do althought I checked all the code several times. There is no need to know about utils class since there are just some debug messages. Did anyone know how to fix it?
What is the meaning of static signal? In Qt signals and slots are used on object level.
signals:
static void NotifyConnected();
static void NotifyDisconnected();
All classes that inherit from QObject or one of its subclasses (e.g., QWidget) can contain signals and slots. Signals are emitted by objects when they change their state in a way that may be interesting to other objects. This is all the object does to communicate. It does not know or care whether anything is receiving the signals it emits. This is true information encapsulation, and ensures that the object can be used as a software component. Signal Slots documentation
I have a qt thread in my application which emits a Mat type image so that other threads can use it. the image is coming from camera by using VideoCapture Object of opencv library. now what i intend to do is getting this image from a rostopic, not from camera directly. in order to do that i must create a ros node in my thread and here i am stuck. is there anyone who has the experience to integrate ros node and qt?
here is my thread:
#include "../include/Ground_Station/camera.h"
#include <iostream>
using namespace std;
Camera::Camera()
{
}
void Camera::run()
{
VideoCapture cap;
cap.open(0);
while(1){
Mat image;
cap >> image;
cvtColor(image,image,CV_BGR2RGB);
emit ImgSignal(&image);
QThread::msleep(30);
}
}
and Camera.h:
#ifndef CAMERA_H
#define CAMERA_H
#include <QObject>
#include <QThread>
#include <QtCore>
#include <QtGui>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <ros/ros.h>
#include <opencv2/opencv.hpp>
using namespace cv;
class Camera: public QThread
{
Q_OBJECT
public:
Camera();
void run();
bool Stop = false;
signals:
void ImgSignal(Mat*);
private:
public slots:
};
#endif // THREAD_H
Basically, your executable file containing the main() function must be your ros node and your QT application at the same time. In your "main.cpp"
you call ros::init(...) and subscribe to the topic you want to listen to. Your subscriber callback function may convert the ros image to Mat and emmit an ImgSignal every time it is called. To do all that, I'd create a RosImageProvider class, something along the lines ..
class RosImageProvider: public QObject
{
Q_OBJECT
public:
void ImageSubscriberCallback(const sensor_msgs::Image::ConstPtr& img);
...
signals:
void ImgSignal(Mat*);
};
I encountred the same problem when dealing with TCP/IP connection from a ROS node within Qt and my solution was to inherit directly from the QThread object, thus when initializing the class, you initialize the ROS node and implement the work TODO in callbacks and the thread run() function.
So finally, my code looked something like this :
#ifndef INCLUDE_TCPHANDLER_HPP_
#define INCLUDE_TCPHANDLER_HPP_
#include <ros/ros.h>
#include <QThread>
#include <string>
class TCP_Handler : public QThread
{
Q_OBJECT
private:
int init_argc;
char** init_argv;
ros::Publisher cmd_control_publisher;
ros::Subscriber feedback_subscriber;
public:
TCP_Handler()
{}
virtual ~TCP_Handler(){}
/**
* #brief ROS methods
*
*/
inline bool init_ros()
{
int argc =0; char** argv = new char*();
ros::init(argc,argv,"tcp_handler");
ros::NodeHandle n;
cmd_control_publisher = n.advertise<robot_common::cmd_control>("cmd_control", 1000);
feedback_subscriber = n.subscribe<robot_common::feedback>("wifibot_pose", 4, &TCP_Handler::FeedbackCallback , this);
return true;
}
void FeedbackCallback(const robot_common::feedback::ConstPtr& pose)
{
//.....
}
/**
* #brief Threading methods
*
*/
virtual void init(int, std::string ip_addr = "127.0.0.1") = 0;
virtual void run() = 0;
virtual void stop() = 0;
/**
* #brief TCP methods (Server/Client have to implement these folks)
*
*/
virtual bool Send_data(char* data, int size) = 0;
virtual int Receive_data(char* in_data, int size) = 0;
virtual bool Open_connection() = 0;
virtual void Close_connection() = 0;
};
#endif /* INCLUDE_TCPHANDLER_HPP_ */
This code is just a template of a Qt-threaded-ROS node for TCP connction as I don't know your specific needs. feel free to build your own !
Cheers,
ALL,
I'm using Anjuta to do my development.
I created a project for my main application, and then made 2 more: 1 for the static library (libdbinterface.a) and 1 for the dynamic library (libsqlite_lib.so).
Both those libraries contains one exported class each: libdbinterface.a - class Database, libsqlite_lib.so - public SQLiteDatabase : public Database.
Now I'm trying to link libdbinterface.a to libsqlite_lib.so.
So in Anjuta I added following to the "Linker Option" for the target libsqlite_lib.so:
-L/home/igor/dbhandler/Debug/dbinterface -ldbinterface
However, trying to compile I received following error from linker:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: /home/igor/dbhandler/Debug/dbinterface/libdbinterface.a(database.o): relocation R_X86_64_32S against `_ZTV8Database' can not be used when making a shared object; recompile with -fPIC
I tried to recompile libsqlite_lib.so with -fPIC explicitely added to "C++ Options" of that project but that didn't solve it - I still receive the same error.
Unfortunately trying to Google on how to link .a and .so is not helpful.
Can someone sched some light on how to fix this error?
TIA.
[EDIT]
libsqlite_lib.so Makefile - https://bpaste.net/show/1495231e58cc
libdbinterface.a Makefile - https://bpaste.net/show/3a71c119d0fc
libdbinterface.a contains 2 files databse.h:
#ifndef DBMANAGER_DATABASE
#define DBMANAGER_DATABASE
class Field
{
public:
Field(const std::string &columnName, const std::string &columnType, const std::string &columnDefaultValue = "", const bool columnIsNull = false, const bool columnPK = false)
{
column_name = columnName;
column_type = columnType;
column_defaultValue = columnDefaultValue;
column_isNull = columnIsNull;
column_pk = columnPK;
}
private:
std::string column_name, column_type, column_defaultValue;
bool column_isNull, column_pk;
};
struct FKField
{
FKField(const std::string &table_name, const std::string &original_field, const std::string &referenced_field)
{
tableName = table_name;
originalField = original_field;
referencedField = referenced_field;
}
std::string tableName, originalField, referencedField;
};
class Table
{
public:
Table(const std::string &tableName, const std::vector<Field> &tableFields, const std::map<int,std::vector<FKField> > &foreignKeys)
{
table_name = tableName;
table_fields = tableFields;
foreign_keys = foreignKeys;
}
const std::string &GetTableName() { return table_name; }
std::map<int,std::vector<FKField> > &GetForeignKeyVector() { return foreign_keys; }
private:
std::string table_name;
std::vector<Field> table_fields;
std::map<int,std::vector<FKField> > foreign_keys;
};
#ifdef WIN32
class __declspec(dllexport) Database
#else
class Database
#endif
{
private:
struct Impl;
Impl *pimpl;
public:
Database();
virtual ~Database();
Impl &GetTableVector();
static void *operator new(std::size_t size);
static void operator delete(void *ptr, std::size_t size);
virtual int Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg);
virtual int GetTableListFromDb(std::string &) { return 0; }
};
#endif
and database.cpp:
#ifdef WIN32
#include <windows.h>
#endif
#include <map>
#include <vector>
#include <string>
#include <sqlext.h>
#include "database.h"
struct Database::Impl
{
std::vector<Table> m_tables;
};
Database::Database() : pimpl( new Impl )
{
}
Database::~Database()
{
delete pimpl;
}
void *Database::operator new(std::size_t size)
{
return ::operator new( size );
}
void Database::operator delete(void *ptr, std::size_t size)
{
return ::operator delete( ptr );
}
Database::Impl &Database::GetTableVector()
{
return *pimpl;
}
int Database::Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg)
{
selectedDSN = selectedDSN;
errorMsg = errorMsg;
return 0;
}
libsqlite_lib.so has also 2 files: database_sqlite.h
#ifndef DBMANAGER_SQLITE
#define DBMANAGER_SQLITE
#ifdef WIN32
class __declspec(dllexport) SQLiteDatabase : public Database
#else
class SQLiteDatabase : public Database
#endif
{
public:
SQLiteDatabase();
~SQLiteDatabase();
virtual int Connect(const char *selectedDSN, std::vector<std::wstring> &errorMsg);
virtual int GetTableListFromDb(std::vector<std::wstring> &errorMsg);
protected:
void GetErrorMessage(int code, std::wstring &errorMsg);
private:
sqlite3 *m_db;
};
#endif
and database_sqlite.cpp with the actual implementation.
[/EDIT]
Well, apparently the solution is to rebuild static library with "-fPIC", not the dynamic one.
Thank you for reading.
i'm trying to learn qt.this is my first example that I'm practicing.but i have this error:C:\Qt2\Qt5.2.1\Tools\QtCreator\bin\recognize_signal_slot\main.cpp:19: error: undefined reference to `Counter::valueChanged(int)'
I don't know what I should do..someone told me you should put your class in header file.but I couldn't understand what he said.can anyone tell me step by step.thank you so much.
here is my code in main.cpp :
#include <QCoreApplication>
#include <QObject>
class Counter : public QObject
{
int m_value;
public:
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
};
void Counter::setValue(int value)
{
if (value != m_value)
{
m_value = value;
emit valueChanged(value);
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Counter d, b;
QObject::connect(&d, SIGNAL(valueChanged(int)),
&b, SLOT(setValue(int)));
d.setValue(12); // a.value() == 12, b.value() == 12
return a.exec();
}
[What's Wrong?]
You signals & slots are not invoked by Meta-Object-Compiler (MOC).
Suggested reading: Why Does Qt Use Moc for Signals and Slots?.
[Solution]
Step 1. Add Q_OBJECT macro to the QObject derivatives that use signals & slots.
class Counter : public QObject
{
Q_OBJECT // <-----HERE
int m_value;
public:
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
};
Step 2. move your class declaration to counter.h and implementation to counter.cpp. Since MOC searches header files that contain Q_OBJECT, it's better to keep your QObject classes and main well separate, even for a small test project.
Step 3. Clean all ---> run qmake ---> rebuild (qmake will automatically call MOC to translate signals & slots syntax into compilable C++ code)
I have this class:
#pragma once
#ifndef _DEFINES_H_
#include "Defines.h"
#endif
#ifndef _GAMETIME_H_
#include "GameTime.h"
#endif
#ifndef _UTILITIES_H_
#include "Utilities.h"
#endif
#ifndef _GAME_H_
using namespace System;
namespace BSGameFramework
{
public ref class Game
{
public:
Game();
virtual ~Game();
void Run(HINSTANCE instance);
string Title;
int WindowWidth;
int WindowHeight;
protected:
virtual void Initialize();
virtual void LoadContent();
virtual void UnloadContent();
virtual void Update(GameTime^ gameTime);
virtual void Draw(GameTime^ gameTime);
private:
HINSTANCE windowHandler;
HWND window;
DateTime lastTime;
TimeSpan totalGameTime;
D3D_DRIVER_TYPE driverType_;
D3D_FEATURE_LEVEL featureLevel_;
ID3D11Device* d3dDevice_;
ID3D11DeviceContext* d3dContext_;
IDXGISwapChain* swapChain_;
ID3D11RenderTargetView* backBufferTarget_;
void Shutdown();
};
}
#define _GAME_H_
#endif
and this is its child:
#pragma once
using namespace BSGameFramework;
public ref class MyGame : Game
{
public:
MyGame()
{
}
};
Then when on my Main I call my Run function:
#include <Windows.h>
#include "MyGame.h"
using namespace BSGameFramework;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
MyGame ^game = gcnew MyGame();
game->Run(hInstance); // Here the error
}
I get this error:
Error 1 error C3767: 'BSGameFramework::Game::Run': candidate function(s) not accessible
C:\Users\Nicola\Desktop\directx prove\BSGameFramework\FrameworkTestCpp\Main.cpp 10 1 FrameworkTestCpp
I've tried to remove the HINSTANCE from Run parameters and all is working fine, but I need it so somebody can explain me why I'm getting this error and how can I solve? Thanks in advance!
I have solved in this way:
inline void Game::Run(IntPtr instance)
{
windowHandler = (HINSTANCE)instance.ToPointer();
// other code
}
now I'm passing an IntPtr that is not a native type, so on main function I have this:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
MyGame ^game = gcnew MyGame();
IntPtr instance(hInstance);
game->Run(instance);
}