I'm trying to manage my own Debug system on Qt but I have some issues :
main.h
#include <QCoreApplication>
#include "PhTools/PhDebug.h"
int main(int argc, char *argv[])
{
// Test of Debug tool
DEBUG << "Test";
// Test of TimeCode
for(int i=0; i<3;i++)
{
if(false)
DEBUG << "problem with me";
}
return 0;
}
PhDebug.h
#ifndef PHDEBUG_H
#define PHDEBUG_H
#include <QDebug>
#include <QDate>
#include <QRect>
#define DEBUG PhDebug d; d << PHDEBUG
#define PHDEBUG qDebug() << __FUNCTION__ << ":"
// In order to get rid of double quotes when displaying a variable
#define Q(string) (string).toStdString().c_str()
class PhDebug
{
public:
QDebug operator<<(QDebug dbg)
{
QString d;
d = QDate::currentDate().toString("dd.MM.yyyy");
d += " - ";
d += QTime::currentTime().toString("hh.mm.ss.zzz");
d += " in";
dbg << Q(d);
return dbg;
}
};
#endif // PHDEBUG_H
So the output should be 04.09.2013 - 12.30.51.513 in main : Test but instead I have this :
04.09.2013 - 12.30.51.513 in main : Test
04.09.2013 - 12.30.51.514 in main : problem with me
04.09.2013 - 12.30.51.514 in main : problem with me
04.09.2013 - 12.30.51.514 in main : problem with me
You problem is lack of braces around if(false). The d << PHDEBUG part of your macro still gets executed.
Incidentally, Qt already has a helper that does the same thing as your Q macro: qPrintable
Related
Using Poco-1.12.4-release and g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, The recommended example code for DatagramSocket Receive in this doc:
https://pocoproject.org/slides/200-Network.pdf
compiles with this error:
dgs.cpp: In function ‘int main(int, char**)’:
dgs.cpp:34:33: error: no matching function for call to ‘Poco::Net::DatagramSocket::DatagramSocket(Poco::Net::SocketAddress&)’
34 | Poco::Net::DatagramSocket dgs(sa);
What happened? Is there a fix for this example?
Thanks
The code is:
// DatagramSocket receive example
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include <iostream>
int main(int argc, char** argv)
{
Poco::Net::SocketAddress sa(Poco::Net::IPAddress(), 514);
Poco::Net::DatagramSocket dgs(sa);
char buffer[1024];
for (;;)
{
Poco::Net::SocketAddress sender;
int n = dgs.receiveFrom(buffer, sizeof(buffer)-1, sender);
buffer[n] = '\0';
std::cout << sender.toString() << ": " << buffer << std::endl;
}
return 0;
}
I tried this:
Poco::Net::SocketAddress sa(Poco::Net::IPAddress(), 514);
Poco::Net::DatagramSocket dgs(Poco::Net::SocketAddress::IPv4);
dgs.connect(sa);
It compiles, but is it correct?
I create a "server" lib with a Qt GUI.
I don't and can't use QThreads because this is supposed to be as independent from Qt as possible, and because I have other threads already working like a Ethernet part.
The thread ExternalRs232Thread() is lauched by the public function RunExternalRs232()
RunExternalRs232() opens the serial port, returns -1 if can't open serial, and if is ok runs the function ExternalRs232Thread() in a detached thread.
Initially, I have tried to run this with Serialib, but this never works properly with the Qt project. So I decided to give QSerialPort a try like this:
Server.h
#ifndef SERVER_H
#define SERVER_H
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <sstream>
#include <time.h>
#include <chrono>
#include <mutex>
#include <QObject>
#include "libs/json.hpp"
#include <QtSerialPort>
#include "hdlccsvparser.h"
using namespace std;
using json = nlohmann::json;
using std::chrono::milliseconds;
using std::chrono::duration_cast;
using std::chrono::seconds;
using std::chrono::system_clock;
struct Contact {
int port; //udp port of te contact
time_t time; //last communication date ( is still active ? )
};
class Server : public QObject
{
Q_OBJECT
public:
Server();
virtual ~Server();
[...]
//return 0 if sucess , 1 port is not usabe, 2 port already in use
int RunExternalRs232(string PortCom, unsigned int baudrate);
int StopExternalRs232(string PortCom);
[...]
//clean exit
void ExitServer();
signals:
[...]
private:
[...]
// External ThreadS and exiting loop of threadS in set (if key d'ont exist anymore, exit loop)
mutex mtxExternalRs232;
unordered_set<string> ExternalRs232PortActiveList;
void ExternalRs232Thread(QSerialPort* Rs232Connection, string port);
[...]
};
#endif // SERVER_H
Server.cpp
#include "Server/Server.h"
#include <winsock2.h>
/* Public Part*/
[...]
int Server::RunExternalRs232(string PortCom, unsigned int baudrate){
//PortCom = (char *)"COM1";
//baudrate = 9600;
QSerialPort Rs232Connection;
// Connection to serial port
// COMxx
Rs232Connection.setPortName(QString::fromStdString(PortCom));
Rs232Connection.setBaudRate(baudrate);
Rs232Connection.setDataBits(QSerialPort::Data8);
Rs232Connection.setParity(QSerialPort::NoParity);
Rs232Connection.setStopBits(QSerialPort::OneStop);
Rs232Connection.setFlowControl(QSerialPort::NoFlowControl);
int i = Rs232Connection.open(QIODevice::ReadWrite);
// If connection fails, errorOpening != 1
if(i != 1){
return i;
}
mtxExternalRs232.lock();
ExternalRs232PortActiveList.insert(PortCom);
mtxExternalRs232.unlock();
cout << "External Rs232 starting on " << PortCom << endl;
stringstream sstmp;
sstmp << PortCom;
emit LogMessage(QString::fromStdString("External Rs232 starting on " + sstmp.str()),0);
std::thread thServer(&Server::ExternalRs232Thread,this,&Rs232Connection,PortCom);
thServer.detach();
return 0;
}
int Server::StopExternalRs232(string PortCom){
PortCom = "COM1";
mtxExternalRs232.lock();
/*
if(ExternalRs232PortActiveList.count(PortCom) != 1){ //???
//port not in use
cerr << "close Failed Rs232 " << PortCom << endl;
mtxExternalRs232.unlock();
return 1;
}*/
cout << "close External Rs232 " << PortCom << endl;
ExternalRs232PortActiveList.erase(PortCom);
mtxExternalRs232.unlock();
return 0;
mtxExternalRs232.lock();
cout << ExternalRs232PortActiveList.count(PortCom) << " here " << endl;
mtxExternalRs232.unlock();
}
[...]
/* Private Part */
/* Thread part */
[...]
void Server::ExternalRs232Thread(QSerialPort * Rs232Connection, string port){
//char/binary read on rs232
char tmp;
//if rs232 has data
bool res = false;
stringstream message;
Rs232Connection->write("H");
mtxExternalRs232.lock();
int iscount = ExternalRs232PortActiveList.count(port);
mtxExternalRs232.unlock();
while(iscount == 1){
res = false;
if(!Rs232Connection->waitForReadyRead(300)){
//no data skipp
} else {
QByteArray datas = Rs232Connection->readAll();
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
string tmp = codec->toUnicode(datas).toStdString();
cout << tmp << endl;
}
mtxExternalRs232.lock();
iscount = ExternalRs232PortActiveList.count(port);
mtxExternalRs232.unlock();
}
Rs232Connection->flush();
Rs232Connection->close();
}
[...]
/* functions part */
[...]
Server::Server(){
//init winsock
if(WSAStartup(MAKEWORD(2,2),&wsa) != 0){
cerr << "Could not init winsock2 : " << WSAGetLastError();
}
//creating a socket
if((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET){
cerr << "Could not create a socket : " << WSAGetLastError();
}
}
Server::~Server(){
//dtor
}
at the end, I get
QObject::startTimer: Timers can only be used with threads started with QThreads
So how is possible to run Serial Rs232 without using QThreads?
Is it "expected" for QSharedPointer::create() not to work or is it a bug? I get an error:
/usr/include/qt5/QtCore/qsharedpointer_impl.h:439:9: error:
invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
new (result.data()) T(std::forward<Args>(arguments)...);
casting from nonconst shared pointer and constructor from raw const pointer work.
I got this for Qt5.7.0 and Qt5.10.0.
Here is a minimal example:
#include <QSharedPointer>
struct A {};
int main(int argc, char *argv[])
{
auto ca = QSharedPointer<const A>::create();
return 0;
}
Here is one file (not minimal) example but with few working cases, 2 not working and a debug. Commented defines are for "not compiling" parts.
#include <QSharedPointer>
#include <QDebug>
#define FROM_PTR
//#define CONST_CREATE
#define FROM_RAW_PTR
#define PERFECT_FORWARD_CREATE
//#define PERFECT_FORWARD_CREATE_CONST
#define BUILTIN_CAST
class A
{
public:
A() = default;
A(int i) : _i{i} {}
void foo() const { qDebug() << "const foo" << _i; }
void foo() { qDebug() << "foo" << ++_i; }
private:
int _i{0};
};
using ASPtr = QSharedPointer<A>;
using ASCPtr = QSharedPointer<const A>;
int main(int argc, char *argv[])
{
Q_UNUSED(argc)
Q_UNUSED(argv)
#ifdef FROM_PTR
qDebug() << "FROM_PTR";
auto a1 = ASPtr::create();
a1->foo();
auto ca1 = static_cast<ASCPtr>(a1);
ca1->foo();
qDebug() << "\n";
#endif // FROM_PTR
#ifdef CONST_CREATE
qDebug() << "CONST_CREATE";
auto ca2 = ASCPtr::create();
ca2->foo();
qDebug() << "\n";
#endif // CONST_CREATE
#ifdef FROM_RAW_PTR
qDebug() << "FROM_RAW_PTR";
auto ca3 = ASCPtr(new const A);
ca3->foo();
qDebug() << "\n";
#endif // FROM_RAW_PTR
#ifdef PERFECT_FORWARD_CREATE
qDebug() << "PERFECT_FORWARD_CREATE";
auto a2 = ASPtr::create(10);
a2->foo();
qDebug() << "\n";
#endif // PERFECT_FORWARD_CREATE
#ifdef PERFECT_FORWARD_CREATE_CONST
qDebug() << "PERFECT_FORWARD_CREATE_CONST";
auto ca4 = ASCPtr::create(20);
ca4->foo();
qDebug() << "\n";
#endif // PERFECT_FORWARD_CREATE
#ifdef BUILTIN_CAST
qDebug() << "BUILTIN_CAST";
QSharedPointer<A> a3 = ASPtr::create();
a3->foo();
auto ca4 = a3.constCast<const A>();
ca4->foo();
qDebug() << "\n";
#endif // BUILTIN_CAST
return 0;
}
That is a known Qt bug (QTBUG-49748). Although it is marked as resolved in Qt 5.6.0, the bug is still present as pointed out in the comments.
Why is this happening?
Look at the implmentation of the class QSharedPointer qsharedpointer_impl.h.
In particular the line:
new (result.data()) T(std::forward<Args>(arguments)...);
uses the result.data() as the new expression placement params. Unfortunately, one can not use a const pointer as a placement param (have a look at this question here on SO for more details).
Hence, there's not much you can do except reporting this to Qt developers via the official bug tracker.
You may have a look at the smart pointers provided by the standard library (e.g. std::shared_ptr) if you are not forced to use Qt ones.
UPDATE
As reported in Qt bug tracker, this bug was fixed in version 5.11 (here is the related commit). Basically, they used std::remove_cv to remove the topmost const from the type specified.
I have a problem. I'm writing a small application, which will fetch an image from a website and display it in a QT GUI application.
I use QHttp to do this. The code works if I execute it in main (before GUI is shown), but when I try to implement it, so that the code will run when I click on a button, it doesn't work.
Here's some of the code:
downloader.h - The class that's responsible for creating connection and saving image
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
#include <QObject>
#include <QHttp>
#include <QFile>
#include <QDebug>
#include <QDir>
class Downloader : public QObject
{
Q_OBJECT
public:
explicit Downloader(QObject *parent = 0);
void getImageFromWeb(QString host, QString append);
signals:
public slots:
void stateChanged(int state);
void responseHeaderReceived(const QHttpResponseHeader &resp);
void requestFinished(int id, bool error);
private:
QHttp *http;
};
#endif // DOWNLOADER_H
downloader.cpp - The implementation
The case switches are added for debugging
#include "downloader.h"
#include <QApplication>
Downloader::Downloader(QObject *parent) :
QObject(parent)
{
}
void Downloader::getImageFromWeb(QString host, QString append)
{
http = new QHttp(this);
connect(http, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)));
qDebug() << "Connect 1";
connect(http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(responseHeaderReceived(QHttpResponseHeader)));
qDebug() << "Connect 2";
connect(http, SIGNAL(requestFinished(int,bool)), this, SLOT(requestFinished(int,bool)));
qDebug() << "Connect 3";
http->setHost(host);
http->get(append);
}
void Downloader::stateChanged(int state)
{
switch(state)
{
case 0:
qDebug() << "Unconnected";
break;
case 1:
qDebug() << "Hhost Lookup";
break;
case 2:
qDebug() << "Connection";
break;
case 3:
qDebug() << "Sending";
break;
case 4:
qDebug() << "Reading";
break;
case 5:
qDebug() << "Connect";
break;
case 6:
qDebug() << "Closing";
break;
}
}
void Downloader::responseHeaderReceived(const QHttpResponseHeader &resp)
{
qDebug() << "Size" << resp.contentLength();
qDebug() << "Type" << resp.contentType();
qDebug() << "Status" << resp.statusCode();
}
void Downloader::requestFinished(int id, bool error)
{
if(error)
{
qDebug() << "ERROR!";
}
else
{
qDebug() << "OK";
QFile *file = new QFile(QDir::currentPath() + "/image.png");
if(file->open(QFile::Append))
{
file->write(http->readAll());
file->flush();
file->close();
}
delete file;
}
}
main.cpp - The code above works correctly if it is implemented like this
#include "mainwindow.h"
#include <QApplication>
#include <downloader.h>
int main(int argc, char *argv[])
{
Downloader getImage;
getImage.getImageFromWeb("servlet.dmi.dk", "/byvejr/servlet/byvejr?by=8000&tabel=dag3_9");
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Instead of this, I would like the image to be fetched when I press a button in the program, so I tried this:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "downloader.h"
#include <QApplication>
#include <QDir>
void MainWindow::on_pushButton_clicked()
{
Downloader getImage;
getImage.getImageFromWeb("www.dmi.dk/", "/uploads/tx_dmidatastore/webservice/k/d/_/n/g/femdgn_dk.png");
}
This doesn't work. From the debugger I get:
Connect 1
Connect 2
Connect 3
When it works (when it's implemented in main.cpp) the debugger gives me something like:
Connect 1
Connect 2
Connect 3
OK
Connection
Sending
Reading
Size 16282
Type "image/png"
Status 200
Connect
OK
So I guess this tells me that the connections are made, but nothing is being executed.
Any answer/suggestion is appreciated.
Thanks in advance!
Looks like your getImage object is being descoped/destructed before it can do anything. Try creating a Downloader object as a member of MainWindow instead of inside the on_pushButton_clicked() function.
I have a rellly long process that produces about 700 Mb of a txt log output file. This is very hard to manage. So I want to divide the output in multiple smaller log files. This is what my main.cpp looks like
#include <QtGui/QApplication>
#include "mineedit.h"
#include "logoutput.h"
#include <iostream>
void messageHandling(QtMsgType type, const char *msg){
if (ERRORLOGGER.isEmpty()){
ERRORLOGGER = DEFERRORLOGGER;
}
std::cout << "In Message Handling" << std::endl;
std::cout << "Writing to file" << ERRORLOGGER.toStdString() << std::endl;
QFile file(ERRORLOGGER);
file.open(QFile::Append);
QTextStream stream(&file);
switch (type) {
case QtDebugMsg:
stream << msg << "\n";
file.close();
break;
case QtWarningMsg:
stream << "WARNING: " << msg << "\n";
file.close();
break;
case QtCriticalMsg:
stream << "CRITICAL: " << msg << "\n";
file.close();
break;
case QtFatalMsg:
stream << "FATAL: " << msg << "\n";
file.close();
abort();
}
}
int main(int argc, char *argv[])
{
ERRORLOGGER = DEFERRORLOGGER;
qInstallMsgHandler(messageHandling);
QApplication a(argc, argv);
MineEdit w;
w.show();
return a.exec();
}
[/CODE]
And my logoutput.h is like
#ifndef LOGOUTPUT_H
#define LOGOUTPUT_H
#include <QString>
//----------------------------For outputting an error file------------------------------
#define DEFERRORLOGGER "/home/aarelovich/Documents/log.err"
#define FOLDER_OUTPUT_LOG "./home/aarelovich/Documents"
extern QString ERRORLOGGER;
#endif // LOGOUTPUT_H
Now in a part of my code I do:
ERRORLOGGER = name_of_current_log_file.
However I get the following compilation errors:
obj/main.o: In function messageHandling(QtMsgType, char const*)':
/home/aarelovich/Dropbox/MineSim/main.cpp:8: undefined reference toERRORLOGGER'
/home/aarelovich/Dropbox/MineSim/main.cpp:9: undefined reference to ERRORLOGGER'
/home/aarelovich/Dropbox/MineSim/main.cpp:13: undefined reference toERRORLOGGER'
/home/aarelovich/Dropbox/MineSim/main.cpp:15: undefined reference to ERRORLOGGER'
obj/main.o: In functionmain':
/home/aarelovich/Dropbox/MineSim/main.cpp:40: undefined reference to ERRORLOGGER'
obj/mineedit.o:/home/aarelovich/Dropbox/MineSim/mineedit.cpp:101: more undefined references toERRORLOGGER' follow
collect2: ld returned 1 exit status
Can anyone please tell me what am I doing wrong? Or how I can dynamically change the output file in which I create my application log?
Thanks for any help
Your problem is probably related to extern variable.
Here is an example of how to use extern keyword in c++.
Beware that C++ and C have differences with extern keyword when linking.
Basicall what you need to do is
global.cpp:
// declaration of g_nValue
int g_nValue = 5;
main.cpp:
// extern tells the compiler this variable is declared elsewhere
extern int g_nValue;
int main()
{
g_nValue = 7;
return 0;
}
In your example if you use extern QString ERRORLOGGER; in logoutput.h,
this variable needs to be declared in another cpp just as explained in the link.
I hope this helps