I am trying to build a simple application in QML that when a button was pressed an external program was lanch. I search a lot, but 99% of the solutions are similar to this. When I compile the error is:
Undefined symbols for architecture x86_64:
"ProcessStarter::qt_metacall(QMetaObject::Call, int, void**)", referenced from:
vtable for QQmlPrivate::QQmlElement<ProcessStarter> in main.o
"ProcessStarter::qt_metacast(char const*)", referenced from:
vtable for QQmlPrivate::QQmlElement<ProcessStarter> in main.o
"ProcessStarter::staticMetaObject", referenced from:
int qmlRegisterType<ProcessStarter>(char const*, int, int, char const*) in main.o
QtPrivate::MetaObjectForType<ProcessStarter*, void>::value() in main.o
QMetaTypeIdQObject<ProcessStarter*, 8>::qt_metatype_id() in main.o
"ProcessStarter::metaObject() const", referenced from:
vtable for QQmlPrivate::QQmlElement<ProcessStarter> in main.o
"typeinfo for ProcessStarter", referenced from:
typeinfo for QQmlPrivate::QQmlElement<ProcessStarter> in main.o
"vtable for ProcessStarter", referenced from:
ProcessStarter::ProcessStarter(QObject*) in main.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The code of main.cpp is:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QProcess>
#include <QVariant>
#include <QQmlContext>
class ProcessStarter : public QProcess
{
Q_OBJECT
public:
ProcessStarter(QObject *parent = 0) : QProcess(parent) { }
virtual ~ProcessStarter() = default;
Q_INVOKABLE void start(const QString &program, const QVariantList &arguments)
{
QStringList args;
// convert QVariantList from QML to QStringList for QProcess
for (int i = 0; i < arguments.length(); i++)
args << arguments[i].toString();
QProcess::start(program, args);
}
Q_INVOKABLE QByteArray readAll() {
return QProcess::readAll();
}
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<ProcessStarter>("Process", 1, 0, "ProcessStarter");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
Instead the main.qml is:
import QtQuick 2.12
import QtQuick.Controls 2.0
import QtQuick.Window 2.12
import Process 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ProcessStarter {
id: process
onReadyRead: console.info(readAll())
}
Button {
onClicked: {
process.start("../prova", [ "-a", "-b"])
}
}
}
I can't understand where is the mistake! Regards Marco