I am working on a c++ measurement software which uses a 3rd party API for the interface all sensors are connected to. This API is not open source and no debug library is available.
In some occasions, the software freezes when starting to read a value from the interface. While I could not determine what criterions cause the problem and why it only happens sometimes so far, I'd like to intercept the freezing and implement some error handling, which would also allow me to better debug the issue.
In my code, I simply have a call
BOOL result = false;
result = pciadioAIStartConversion(board_index, channel_nr, range);
where, if the error occurs, pciadioAIStartConversion never returns. I am looking for some simple functionality to keep the software running and return if the call takes to long.
I am using the Qt framework (4.8.6) so a possible solution would be using the event system and a QTimer, but therefore the call would need its own thread if I'm not mistaken and that seems like overkill to me.
piezol is right You need a separate thread which can be quite a mess but the good news is that Qt thread framework (which is called QtConcurrent) is really helpful.
Here is an example for running a standard function in a separate thread mantaining control of it.
#include <QDebug>
#include <QThread>
#include <QString>
#include <qtconcurrentrun.h>
#include <QApplication>
using namespace QtConcurrent;
void hello(QString name)
{
qDebug() << "Hello" << name << "from" << QThread::currentThread();
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QFuture<void> f1 = run(hello, QString("Alice"));
QFuture<void> f2 = run(hello, QString("Bob"));
f1.waitForFinished();
f2.waitForFinished();
}
Related
I'm trying hardly to convert the Modbusmaster example (qt example) which is a widget application to a console application. I wanted to build a connection between a local slave and my master. The problem I'm facing is that my code is changing its state to “Connecting state” ,gets stuck and doesn't want to build a connection. That's why, I recon that the Modbus library is limited and it's only compatible with the widget form.
Could someone tell me if my guesses are right.
down below you will find my code:
#include <QCoreApplication>
#include <QDebug>
#include <QModbusDataUnit>
#include<iostream>
#include <QTimer>// this bib was add to the 50ms Loop check
#include <string>
#include <QString>
#include <QThread>
#include <QModbusTcpClient>
#include <QModbusDataUnit>
#include <QUrl>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Mainmodbus T ;
T.modbusDevice = new QModbusTcpClient();
if (!T.modbusDevice) qDebug()<<"error 1";
if (T.modbusDevice->state() != QModbusDevice::ConnectedState) {
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
T.modbusDevice->connectDevice();
while(true){
qDebug()<<T.modbusDevice->state();}
}
return a.exec();
}
I can be wrong but I think the QModbusDevice::ConnectingState you see actually means your server is up and running and waiting for a connection.
I guess what you are missing is opening a connection from a Modbus client. You can do that with different tools, I guess running the client example
would be a good idea. Otherwise, you can use QModMaster or any other tool you like.
Once you open the connection from the client the state on your server should change to QModbusDevice::ConnectedState.
Be aware that the server you built is just an empty shell, there is no register map defined so if you query the contents of any register from the client you will get an error.
At the very minimum, you should at least define a map with some default values or get them from command-line options. To do that you need to look at the server example a bit more carefully.
First you need to define the register map with something like this:
QModbusDataUnitMap reg;
reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 });
reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 });
reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 });
reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 });
modbusDevice->setMap(reg);
setupDeviceData();
And then for the setupDeviceData(); you can copy the function in the example but instead of taking the data from the widget, you will have to load default values or something from the command line.
In answer to your question: no, there should be no limitation and you should be able to run the server from the command line. I wonder why somebody on his/her right mind would want to do that when you have excellent alternatives like libmodbus. But honestly, I won't miss much sleep wondering.
Qt recently started crashing without having a reason for it. The most recent one which is currently grinding my nerves down to a pulp is crashing due to starting another form programmatically. The "must construct QApplication before a QWidget" apparently is a common issue with Qt 5.7.* versions and the solutions I have found so far in StackOverflow haven't helped me.
This is a screenshot of the error message I got after the application crashed:
And here is the bit of the code that I remove which allows me to restart the application without any noticeable problems:
#include "operations.h"
Operations o;
void mainWindow::on_thisButton_clicked()
{
o.show();
this->hide();
}
----
The main.cpp as requested :)
#include "mainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
mainWindow w;
w.show();
return a.exec();
}
Try this:
#include "operations.h"
void mainWindow::on_thisButton_clicked()
{
Operations *o = new Operations();
o->show();
this->hide();
}
You might want to declare Operations *o as a member of mainWindow and initialize it the the constructor if you don't want to create a new one each time the button is clicked.
"must construct QApplication before a QWidget" is the standard type of error you get with Qt applications, when linking something incompatible ( like mixing debug/release ).
So in most use cases this indicates a build problem and has nothing to with the code itself.
Don't create Operations object as a global variable, as it will be created as a static BEFORE running main(), therefore the error message is simply correct and relevant. This is a C++ issue, not a Qt one.
All other suggestions work because you now create the object at the right time, after the QApplication...
Okay, I have managed to find a solution, however, it is borderline idiotic as it does not make any sense why it does not work in its prior state. Technically, all you need to do in order to have the error not appearing is to stick the declaration of the form class you are referring within the function itself(ie Operations o;).
Here is the code solution itself:
#include "operations.h"
void mainWindow::on_thisButton_clicked()
{
Operations o;
o.show();
this->hide();
}
Bare in mind that this is not the end of all problems as I currently have the problem of the new form closing in the very same 1 second period it opens. If I manage to solve it I will update my solution.
I have a QSharedMemory to prevent that two processes of my application are running at the same time. Process A sets the QSharedMemory to "locked" when started. Now my process B sets a value like "please come back to foreground".
Is there an easy way for process A to observe changes in the QSharedMemory, i.e. avoids implementing a stupid pulling timer?
Here we are: QSystemSemaphore
Like its lighter counterpart QSemaphore, a QSystemSemaphore can be accessed from multiple threads. Unlike QSemaphore, a QSystemSemaphore can also be accessed from multiple processes.
Like QSharedMemory, QSystemSemaphore uses a key-based access method.
Instead of using shared memory, the process could open a QLocalSocket to a named local server, and when it fails, open a QLocalServer. All subsequent processes will success to open the socket to the server, and can communicate with it. That's probably the simplest, most portable way of accomplishing the job.
You can also use QtSingleApplication, iff it has been ported to Qt 5.
To answere your question: No, QSharedMemory does not have such a feature.
If you just want to have a "single instance" application, you can use https://github.com/Skycoder42/QSingleInstance.
It makes shure you have only 1 instance of you application at a time, can automatically bring the active window to the front and allows you to pass parameters from the new process to the running one.
Simple example:
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <qsingleinstance.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSingleInstance instance;
MainWindow *w = NULL;
instance.setStartupFunction([&]() -> int {
w = new MainWindow(NULL);
instance.setNotifyWindow(w);
w->show();
return 0;
});
QObject::connect(qApp, &QApplication::aboutToQuit, [&](){
delete w;
});
QObject::connect(&instance, &QSingleInstance::instanceMessage, [&](QStringList args){
QMessageBox::information(w, "Message", args.join('\n'));
});
return instance.singleExec();
}
This will show the mainwindow, just like you woudl expect. If the application is run a second time, the currently running mainwindow will be raised to the foreground and a messagebox with the arguments will be shown.
Note: This example uses the QWidgets, but the QSingleInstance can be used with a gui or core application, too.
Recently started doing some programming for Windows and I simply can't get my program to work. I am trying to achieve an environment in which I mainly can use HTML for the frontend and control the backend with Javascript. On Linux I've managed to add functions and stuff to the "JavaScriptCore" but Windows haven't been to kind with me.
Currently I'm trying to catch the URL change event, allowing for special URLs to execute commands, however I get the following error:
error: C2664: 'connect' : cannot convert parameter 1 from 'QWebView *' to 'SOCKET'
There is no context in which this conversion is possible
I didn't manage to find a single search result concerning "QWebView to SOCKET" so I have no clue what to do but to ask you guys.
Here is my code. I'm not too good with programming to please be gentle ;)
#include <QtGui>
#include <QtWebKit>
#include <QApplication>
#include <QWebView>
#include <iostream>
using namespace std;
void test()
{
cout << "Hello world";
}
int main(int argc, char** argv) {
QApplication app(argc, argv);
QWebView view;
view.setWindowFlags(Qt::CustomizeWindowHint);
view.setWindowFlags(Qt::FramelessWindowHint);
view.setFixedSize(1000,600);
view.setStyleSheet("background:transparent;");
view.setAttribute(Qt::WA_TranslucentBackground);
view.setUrl(QUrl("http://google.com"));
view.setWindowTitle("test v0.1");
connect(view, SIGNAL(urlChanged(QUrl)), SLOT(test()));
view.show();
return app.exec();
}
Try this instead:
QObject::connect(&view, &QWebView::urlChanged, test);
You are using the old connection syntax which works only with QObjects and slots, test is not a slot and it is not a function of a QObject derived class, it is a free funciton, so you have to use the new syntax, available since Qt 5.
When you are not inside a QObject you don't have access to connect(), that is why my example uses the QObject namespace to invoke it in main(). In your case as DNT noted it is just some other function that happens to be named "connect".
Another mistake you made is you passed the view, but connect() works with pointers, so you have to use the & operator to get a pointer to the view.
I am trying to write an application program that can start another application using c++ in linux . Starting another application is not the problem . The problem I am facing is, that the parent application pauses till the child application is closed. I want the parent application to run along with the child application so that more functionalities of the parent application can be used. How do i go about it?
It would help me a lot if somebody could give me an idea on this.
The application consists of two files main.cpp and a virtualbotmain.cpp. The part of the
virtualbotmain.cpp: #include <iostream>
#include <stdlib.h>
VirtualBotMain::VirtualBotMain(QWidget *parent) :
QWidget(parent),
ui(new Ui::VirtualBotMain)
{
ui->setupUi(this);
}
void VirtualBotMain::on_enterButton_clicked()
{
QString enterString = ui->enterEdit->text();
ui->convoText->append("User: " + enterString);
ui->enterEdit->setText("");
if(enterString=="word")
{
ui->convoText->append("Joe: done..!!");
system("gedit");
}
}
The main.cpp is :
#include <QtGui/QApplication>
#include "virtualbotmain.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
VirtualBotMain w;
w.show();
return a.exec();
}
This is a GUI application that can be used to just type in the application i am trying to open and the application will do it for me. So trying to open many applications one after the other is becoming a problem as the GUI application won't work untill i close the previously opened application.
If you're using a system call (or a similar way to invoke the shell), you can apply the same logic you'd apply in your terminal to start a process "in the background":
system("./myProgram &");
// ^
// run in background
Better alternatives include forking, though it really depends on your specific requirements, which we do not know.
#include <stddef.h>
#include <process.h>
int status = spawnl( P_NOWAIT, "myprog", "myprog", "ARG1", "ARG2", NULL );