Obtaining command line arguments in a Qt application - c++

The following snippet is from a little app I wrote using the Qt framework. The idea is that the app can be run in batch mode (i.e. called by a script) or can be run interactively.
It is important therefore, that I am able to parse command line arguments in order to know which mode in which to run etc.
[Edit]
I am debugging using Qt Creator 1.3.1 on Ubuntu Karmic. The arguments are passed in the normal way (i.e. by adding them via the 'Project' settings in the Qt Creator IDE).
When I run the app, it appears that the arguments are not being passed to the application. The code below, is a snippet of my main() function.
int main(int argc, char *argv[])
{
//Q_INIT_RESOURCE(application);
try {
QApplication the_app(argc, argv);
//trying to get the arguments into a list
QStringList cmdline_args = QCoreApplication::arguments();
// Code continues ...
}
catch (const MyCustomException &e) { return 1; }
return 0;
}
[Update]
I have identified the problem - for some reason, although argc is correct, the elements of argv are empty strings.
I put this little code snippet to print out the argv items - and was horrified to see that they were all empty.
for (int i=0; i< argc; i++){
std::string s(argv[i]); //required so I can see the damn variable in the debugger
std::cout << s << std::endl;
}
Does anyone know how I can retrieve the command line args in my application?

If your argc and argv are good, I'm surprised this would be possible as QApplication::arguments() is extremely simple. Note the source code. Filtering the #ifdefs for Linux, it's just:
QStringList QCoreApplication::arguments()
{
QStringList list;
if (!self) {
qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
return list;
}
const int ac = self->d_func()->argc;
char ** const av = self->d_func()->argv;
for (int a = 0; a < ac; ++a) {
list << QString::fromLocal8Bit(av[a]);
}
return list;
}
That's all you've got. There's a Unicode caveat which I would not think would apply to Karmic:
"On Unix, this list is built from the argc and argv parameters passed to the constructor in the main() function. The string-data in argv is interpreted using QString::fromLocal8Bit(); hence it is not possible to pass, for example, Japanese command line arguments on a system that runs in a Latin1 locale. Most modern Unix systems do not have this limitation, as they are Unicode-based."
You might try a copy of that code against your argc and argv directly and see what happens.

Only in order to keep response up-to-date, Qt now provides a dedicated class for parsing command line:
http://doc.qt.io/qt-5/qcommandlineparser.html
P.S. : can only post this as response and not a comment; I'm sorry because the question was not really how to parse but how to access.

If you are writing a Console only application then you might want to consider using QCoreApplication instead of QApplicition. QCoreApplication is part of QtCore while QApplication is defined in QtGui, so you get an extra and unnecessary dependency.

here is a simple example to have the arguments in a QStringList. Assuming you start the app with argument -q -t
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
QString x;
for (int i=1; i<argc; i++)
{
x.append(argv[i]);
}
qDebug() << x;
QStringList args = x.split("-");
args.removeFirst();
qDebug() << "args="<< args;
return a.exec();
}
Output is as follow
x= "-q-t"
args= ("q", "t")
Now you have the arguments as a QStringList ..
and here is a complete code i wrote and use in a small application
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
static QStringList arguments;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
//analyze the arguments
//-b: use buidin player and if it does not exist use mpg123 shell to play files
//
//-t: test the player upon startup and exit
//-s: use the following speaker ID for the test
//-f: use the following file name and path
//syntax: example:
// -b : to use build in player
// -t -s xx:xx:xx:xx:xx -f azanfile.mp3: to test upon startup playing a file
bool useBuildInPlayer;
QString x;
for (int i=1; i<argc; i++)
{
x.append(argv[i]);
}
arguments << x.split("-"); arguments.removeFirst();
qDebug() << arguments;
if (arguments.indexOf("b")>=0)
useBuildInPlayer=true;
else
useBuildInPlayer=false;
bool TestSpeaker = false;
bool spkr=false; QString speaker;
bool playfile=false; QStringList testfiles;
QString filestring;
foreach (QString x, arguments)
{
if (x.left(1)=="s")
{
speaker = x.mid(1,-1); //remove the s from the beginning
spkr=true;
}
if (x.left(1)=="f")
{
filestring=x.mid(1,-1);
playfile=true;
testfiles<<filestring;
}
if (x=="t")
TestSpeaker = true;
}
if (TestSpeaker)
{
if (spkr)
{
qDebug() << "testing speaker "<< speaker;
}
else
{
qDebug() << "test argument needs speaker -s xx:xx:xx:xx:xx";
}
if (playfile)
{
qDebug() << "testing file "<< filestring;
}
else
{
qDebug() << "test file is missing";
}
}
if (TestSpeaker && spkr && playfile)
{
if (useBuildInPlayer) //use build in player
{
qDebug() << "testing using buildin player";
}
else // use mpg123 shell
{
qDebug() << "testing using mpg123 shell";
}
}
return a.exec();
}

Related

For loop not incrementing only when qInfo looks for array value

#include <QCoreApplication>
int ages[4] = {23,7,75,1000};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qInfo() << ages;
for (int i = 0; i < 5; i++){
qInfo() << i;
}
a.exec();
return 0;
}
returns:
0x7ff7d01f3010 0 1 2 3 4
To the terminal
But
#include <QCoreApplication>
int ages[4] = {23,7,75,1000};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qInfo() << ages;
for (int i = 0; i < 5; i++){
qInfo() << i;
qInfo() << ages[i];
}
a.exec();
return 0;
}
returns:
4713 0 4714 0 4715 0 4716 0 4717 0 4718
etc. to the terminal.
As a beginner this behavior is not intuitive and I do not understand what the difference is.
The first code was my attempt to see if my for loop was written incorrectly, but it acts as expected.
You have undefined behaviour in your code because you are indexing the array out of its size. Your array has four elements, but you seem to try to access 5 elements in its. So, the last iteration is undefined behaviour.
You could write this instead:
#include <QCoreApplication>
int ages[4] = {23,7,75,1000};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qInfo() << ages;
for (int age : ages)
qInfo() << age;
a.exec();
return 0;
}
Depending on your compiler, you could use the sanitizer options to catch these, for example:
-fsanitize=undefined
I personally use these in my projects:
if (CMAKE_CXX_COMPILER_ID MATCHES "(Clang|GNU)")
add_compile_options(-Wall -Wpedantic -Wextra -Werror)
add_compile_options(-fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer)
add_link_options(-fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS "/w")
endif()
add_compile_definitions(QT_DISABLE_DEPRECATED_BEFORE=0xFFFFFF)
I would also like to point out that you should use size_t instead of int for the loop counter as a good practice.
It is also worth pointing out that you should avoid using raw arrays in a C++, and especially Qt program. There are better choices, like:
std::array
std::vector
QList
etc.
Furthermore, you could even merge these two lines:
a.exec();
return 0;
Into the following (this is how it is typically written):
return a.exec();

Passing C++ command line arguments inside main(), yet do the same job

Is there a way to keep the command line argument as standard and yet pass the argv internally inside the main?
Like, change this:
int main(int argc, char **argv) {
App app(argc,argv);
return app.exec();
}
to something like this:
int main(int argc, char **argv) {
vector<string> argv ="arguments";
int argc = X;
App app(argc,argv);
return app.exec();
}
When I have:
./a.out -a A -b B -c C
I know this is weird. I just want to find a workaround not to change the source code of a huge project and just run my command line arguments every time with only ./a.out.
Put each of your arguments in a char array, and then put pointers to those arrays into an array of pointers.
char arg1[] = "./a.out";
...
char argN[] = "whatever";
char* argv[] = { arg1, ..., argN}
App app(N, argv);
You may be looking for
const char *myArgv[]={"-a","A","-b","B"};
int myArgc=4;
App app(myArgc,myArgv);
return app.exec();
std::vector<std::string> args(argv, argv+argc);
You may rename arguments passed to app as you wish to avoid a name conflict, for ex.
int main(int argc, char **argv) {
vector<string> app_argv = /* contents */;
int app_argc = app_argv.size() ;
App app(app_argc, app_argv);
return app.exec();
}

QAudioOutput - application size is continuously growing

I'm trying to write into buffer for QAudioOutput every 20ms. When I try to execute this code I can see the size of process increases about 4-8 kB per second. I was trying to find some function to clear internal buffer of QIODevice or DAudioOuptut but had no luck.
I'm using Qt 5.2.1
In the example below is written only silence(zeros) but it has the same effect:
#include <QLibraryInfo>
#include <QtCore/QCoreApplication>
#include <windows.h> // for Sleep
#include <QAudioOutput>
#include <QAudioDeviceInfo>
#include <QAudioFormat>
#include <array>
class QAudioOutput;
int main(int argc, char *argv[])
{
// Create QApplication
QCoreApplication app(argc, argv);
app.setApplicationName("Audiotest");
//Initialize device
QIODevice * _output;
QAudioDeviceInfo _device = QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat _format;
_format.setSampleRate(44100);
_format.setChannelCount(2);
_format.setSampleSize(16);
_format.setCodec("audio/pcm"); // This codec should be supported on all platforms and plugin implementation
_format.setByteOrder(QAudioFormat::LittleEndian);
_format.setSampleType(QAudioFormat::SignedInt);
if (!_device.isFormatSupported(_format)) {
printf("Default format not supported - trying to use nearest.\n");
_format = _device.nearestFormat(_format);
}
QAudioOutput * _audioOutput = new QAudioOutput(_device, _format);
_output = _audioOutput->start();
std::array<char, 32768> _buffer;
_buffer.fill(0);
for (;;) {
const int periodSize = _audioOutput->periodSize();
const int chunks = _audioOutput->bytesFree() / periodSize;
for (int i = 0; i < chunks; ++i) {
const qint64 len = periodSize;
if (len && _output) {
_output->write(_buffer.data(), len);
}
if (len != periodSize) {
break;
}
}
Sleep(20);
}
return 0;
}
When your loop runs, nothing else does. Your code should be asynchronous, and you should invert the control flow. React to a notification by the audio output device that it has processed a certain interval of samples.
To receive the first notification, you need to prime the device with some data.
// https://github.com/KubaO/stackoverflown/tree/master/questions/audio-37993427
#include <QtMultimedia>
#include <array>
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
auto device = QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
if (!device.isFormatSupported(format))
qFatal("Default format not supported");
QAudioOutput audioOutput{device, format};
auto output = audioOutput.start();
qDebug() << audioOutput.state();
std::array<char, 32768> buffer;
buffer.fill(0);
auto write = [&]{
qDebug() << "notify";
auto periodSize = audioOutput.periodSize();
auto chunks = audioOutput.bytesFree() / periodSize;
for (int i = 0; i < chunks; ++i) {
if (periodSize && output) {
auto len = output->write(buffer.data(), periodSize);
if (len != periodSize)
break;
}
}
};
audioOutput.setNotifyInterval(20);
QObject::connect(&audioOutput, &QAudioOutput::notify, write);
write();
return app.exec();
}
Don't run your own event loop; instead, connect the QAudioOutput's notify signal to a slot in one of your QObjects, and have that slot call write() one time. The notify signal will be emitted whenever the QAudioOutput needs some more audio data to play.
All of this will happen inside QApplication::exec(), which you should call (near the end of main()) to run the Qt event loop for you, rather than your own for-loop.

Cannot Give a Parameter To QT connect Function

I implemented reading bytes at a serial communication in a Qt project(5.5) in Visual Studio 2013.
My code is here:
main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
//QCoreApplication coreApplication(argc, argv);
int argumentCount = QCoreApplication::arguments().size();
QStringList argumentList = QCoreApplication::arguments();
QTextStream standardOutput(stdout);
if (argumentCount == 1) {
standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl;
return 1;
}
QSerialPort serialPort;
QString serialPortName = argumentList.at(1);
serialPort.setPortName(serialPortName);
int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600;
serialPort.setBaudRate(serialPortBaudRate);
if (!serialPort.open(QIODevice::ReadOnly)) {
standardOutput << QObject::tr("Failed to open port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
Camera cam2;
//cam2.showCamera();
cam2.showCamera();
cam2.showFullScreen();
QByteArray abc;
SerialPortReader serialPortReader(&serialPort,abc);
//return coreApplication.exec();
return app.exec();
};
serialportreader.cpp
#include "serialportreader.h"
#include <QCoreApplication>
QT_USE_NAMESPACE
SerialPortReader::SerialPortReader(QSerialPort *serialPort, QByteArray abc, QObject *parent)
: QObject(parent)
, m_serialPort(serialPort)
, m_standardOutput(stdout)
{
connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead);
}
SerialPortReader::~SerialPortReader()
{
}
void SerialPortReader::handleReadyRead()
{
m_readData.append(m_serialPort->readAll());
if (!m_readData.isEmpty()) {
m_standardOutput << m_readData << endl;
m_readData.clear();
}
}
This code works successfully. I would like to set the contents of m_readData array to abc array so that I can evaluate the message in main scope. In order to implement this, I gave abc array to handleReadyRead function as a parameter. However, it gives an error.The code is here:
SerialPortReader::SerialPortReader(QSerialPort *serialPort, QByteArray abc, QObject *parent)
: QObject(parent)
, m_serialPort(serialPort)
, m_standardOutput(stdout)
{
connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead(abc));
}
SerialPortReader::~SerialPortReader()
{
}
void SerialPortReader::handleReadyRead(QByteArray abc)
{
m_readData.append(m_serialPort->readAll());
if (!m_readData.isEmpty()) {
m_standardOutput << m_readData << endl;
m_readData.clear();
}
}
Error:
serialportreader.cpp(45): error C2102: '&' requires l-value
line45:
connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::handleReadyRead(abc));
You can't pass the local variable to the slot this way, but what you are trying to do doesn't even require it. You could just store abc to a member variable in the constructor, and use it in the slot. BUT: you have to change it to a reference, otherwise the call to the constructor copies the array, so the original one in your main function is unaffected.
You could also just implement this array as a member variable of your SerialReader, and provide a getter function, so that the main function (or whoever is the consumer of the data) can just pull this data from the reader instance.

Adding parameters for a program at launch

I'm currently trying to make a small application that performs different duties. Right now I have a console app pop up and ask what I want to do, but sometimes I would rather just launch it with something like MyApp.exe -printdocuments or some such thing.
Are there any tutorials out there that can show me a simple example of this?
In C++, your main() function can have argc and argv parameters, which contain the arguments passed on the command line. The argc is the count of arguments (including the executable name itself), and argv is an array of pointers to null-terminated strings of length argc.
For example, this program prints its arguments:
#include <stdio.h>
int main(int argc, char *argv[])
{
for (int i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
return 0;
}
Any C or C++ tutorial will probably have more information on this.
You can use boost::program_options to do this, If you don't want to use boost library, you must parse main function arguments by yourself.
getopt is a posix function (implementations for windows exist) that can help you parse your arguments:
#include <unistd.h> // getopt
// call with my_tool [-n] [-t <value>]
int main(int argc, char *argv[])
{
int opt;
int nsecs;
bool n_given = false, t_given = false;
// a colon says the preceding option takes an argument
while ((opt = ::getopt(argc, argv, "nt:")) != -1) {
switch (opt) {
case 'n':
n_given = true;
break;
case 't':
nsecs = boost::lexical_cast<int>(optarg);
t_given = true;
break;
default: /* '?' */
std::cerr << "Usage: "
<< argv[0] << " [-t <value>] [-n]\n";
return 1;
}
}
return 0;
}
You would do well to use a library for this. Here are a few links that might get you started on command line arguments with c++.
gperf
your entry point method i.e. in C++ your main method needs to look like
int main ( int argc, char *argv[] );
you can read this article and accomplish what you are trying to do