qt — модуль [] не установлен — регистрация пользовательской оболочки C ++ для QML

Мне нужно получить доступ к C ++ API для работы с шиной CAN. Похоже, что лучшее решение — написать оболочку QML, чтобы раскрыть всю необходимую мне функциональность.

Вот мой canservice.cpp до сих пор:

#include "canservice.h"#include <QCanBus>
#include <QDebug>
#include <QCanBusFrame>
#include <QTimer>

#include <QtCore/qbytearray.h>
#include <QtCore/qvariant.h>
#include <QtCore/qdebug.h>

CANService::CANService(QObject *parent) :
QObject(parent),
m_canDevice(nullptr)
{
QString status = "";

initializeSettings();// TODO" disable sending messages until connection is stablished
}

CANService::~CANService()
{
delete m_canDevice;
}

void CANService::receiveError(QCanBusDevice::CanBusError error) const
{
switch (error) {
case QCanBusDevice::ReadError:
case QCanBusDevice::WriteError:
case QCanBusDevice::ConnectionError:
case QCanBusDevice::ConfigurationError:
case QCanBusDevice::UnknownError:
qWarning() << m_canDevice->errorString();
default:
break;
}
}

void CANService::initializeSettings()
{
foreach (const QByteArray &backend, QCanBus::instance()->plugins()) {
qInfo() << "found: " + backend;
if (backend == "socketcan") {
// found socketcan
m_currentSettings.backendName = "socketcan";
break;
}
}

if(m_currentSettings.backendName.length() < 1) {
qWarning() << "did not find a backend";
}

m_currentSettings.backendName = "socketcan";
m_currentSettings.deviceInterfaceName = QStringLiteral("vcan0");
}

void CANService::connectDevice()
{
m_canDevice = QCanBus::instance()->createDevice(m_currentSettings.backendName.toLocal8Bit(), m_currentSettings.deviceInterfaceName);
if (!m_canDevice) {
showStatusMessage(tr("Connection error"));
return;
}
connect(m_canDevice, &QCanBusDevice::errorOccurred,
this, &MainWindow::receiveError);
connect(m_canDevice, &QCanBusDevice::framesReceived,
this, &MainWindow::checkMessages);
connect(m_canDevice, &QCanBusDevice::framesWritten,
this, &MainWindow::framesWritten);

if (p.useConfigurationEnabled) {
foreach (const ConnectDialog::ConfigurationItem &item, p.configurations)
m_canDevice->setConfigurationParameter(item.first, item.second);
}

if (!m_canDevice->connectDevice()) {
delete m_canDevice;
m_canDevice = nullptr;
qInfo() << "Connection error";
} else {
qInfo() << m_currentSettings.backendName << "is connected";
}
}

void CANService::sendMessage() const
{
if (!m_canDevice)
return;

// TODO: replace test message with input
QByteArray writings = dataFromHex("1122334455667788");

QCanBusFrame frame;
const int maxPayload = 8; // 64 : 8;
int size = writings.size();
if (size > maxPayload)
size = maxPayload;
writings = writings.left(size);
frame.setPayload(writings);

//TODO: get from UI
qint32 id = 100;
if (id > 2047) {
//11 bits
id = 2047;
}

frame.setFrameId(id);
frame.setExtendedFrameFormat(true);

// frame.setFrameType(QCanBusFrame::RemoteRequestFrame);
// frame.setFrameType(QCanBusFrame::ErrorFrame);
frame.setFrameType(QCanBusFrame::DataFrame);

m_canDevice->writeFrame(frame);
}

void CANService::checkMessages()
{
if (!m_canDevice)
return;

const QCanBusFrame frame = m_canDevice->readFrame();

const qint8 dataLength = frame.payload().size();

const qint32 id = frame.frameId();

QString view;
if (frame.frameType() == QCanBusFrame::ErrorFrame) {
interpretError(view, frame);
} else {
view += QLatin1String("Id: ");
view += QString::number(id, 16).toUpper();
view += QLatin1String(" bytes: ");
view += QString::number(dataLength, 10);
view += QLatin1String(" data: ");
view += dataToHex(frame.payload());
}

if (frame.frameType() == QCanBusFrame::RemoteRequestFrame) {
qInfo() << "got remote request message" << view;
} else if (frame.frameType() == QCanBusFrame::ErrorFrame) {
qWarning() << "got can error frame: " << view;
} else {
qInfo() << "got can frame: " << view;
}
}

void CANService::interpretError(QString &view, const QCanBusFrame &frame)
{
if (!m_canDevice)
return;

view = m_canDevice->interpretErrorFrame(frame);
}

static QByteArray dataToHex(const QByteArray &data)
{
QByteArray result = data.toHex().toUpper();

for (int i = 0; i < result.size(); i += 3)
result.insert(i, ' ');

return result;
}

static QByteArray dataFromHex(const QString &hex)
{
QByteArray line = hex.toLatin1();
line.replace(' ', QByteArray());
return QByteArray::fromHex(line);
}

в canservice.h Я имею:

#ifndef CANSERVICE_H
#define CANSERVICE_H

#include <QObject>
#include <QQuickItem>
#include <QCanBusDevice>class CANService : public QObject
{
Q_OBJECT
public:
explicit CANService(QObject *parent = 0);
typedef QPair<QCanBusDevice::ConfigurationKey, QVariant> ConfigurationItem;

struct Settings {
QString backendName;
QString deviceInterfaceName;
QList<ConfigurationItem> configurations;
bool useConfigurationEnabled;
};void connectDevice();

Q_INVOKABLE void connect(const QString &query) {
qDebug() << "invoking connect with " << query;}

explicit ConnectDialog(QWidget *parent = nullptr);
~ConnectDialog();

Settings settings() const;

private:
Settings m_currentSettings;
void initializeSettings();signals:

public slots:

};

qmlRegisterType<MyObject>("can.myapp", 1, 0, "CANService");

#endif // CANSERVICE_H

В моем файле QML я сначала пытаюсь импортировать недавно определенный сервис: import can.myapp 1.0 и затем я объявляю экземпляр этого:

CANService {
id: "myCanService"}

Когда я пытаюсь запустить это приложение и загрузить файл QML, который делает вызов CANService, он не загружается, и я получаю следующую ошибку в консоли приложения:

 component not ready:
"file:///home/aras/Projects/myapp/apps/com.myapp.diagnostics/Diagnostics.qml:5 module \"can.myapp\" is not installed\n"

РЕДАКТИРОВАТЬ:
Проблема скорее всего с тем, куда я звоню qmlRegisterType, я использую appman так что мое приложение не имеет main функция. Где правильное место, чтобы бежать qmlRegisterType от?

0

Решение

Я отвечаю, потому что вы пометили старый пост как похожий.

Вот пара вопросов:
1) Куда ты звонишь? qmlRegisterType<MyObject>("can.myapp", 1, 0, "CANService"); Насколько я понимаю, это нужно назвать в main метод, прежде чем создать экземпляр QtQuickApplicationViewer (если вы загружаете его таким образом.)

2) Работает ли это на простом примере? QString значение функции)?

Сейчас я не активно пишу в Qt, но, надеюсь, это может указать вам правильное направление:

Вот «основной» метод из одного из моих приложений, который использует пользовательские компоненты (для простого подключения Java через командную строку).

#include <QtGui/QGuiApplication>
#include <QtCore>
#include <QtQml>
#include "qtquick2applicationviewer.h"#include "globals.h"#include "lightassistant.h"#include "reporting.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);

//C++ Types
qmlRegisterType<LightAssistant>("com.lightassistant", 1, 0, "LightAssistant");
qmlRegisterType<Reporting>("com.lightassistant", 1, 0, "Reporting");
//Singletons
//qmlRegisterSingletonType(QUrl("file:///qml/LightAssistant/Styles.qml"), "com.lightassistant", 1, 0, "Styles");

QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/LightAssistant/main.qml"));
viewer.showExpanded();
qDebug() << "offline path is " << viewer.engine()->offlineStoragePath();
LA::OFFLINE_STORAGE_PATH = viewer.engine()->offlineStoragePath();
return app.exec();
}

Вот упрощенный класс (эти классы ~ 600 строк)

#ifndefLIGHTASSISTANT_H
#define LIGHTASSISTANT_H

#include <QtSql>
#include <QtCore>
#include <QtXml>
#include <QtXmlPatterns>
#include "globals.h"class LightAssistant : public QObject
{
Q_OBJECT
public:
explicit LightAssistant(QObject *parent = 0);

/**
* Is this running on Android?
*/
Q_INVOKABLE
int isAndroid()
{
#ifdef Q_OS_ANDROID
return 1;
#else
return 0;
#endif
}

/**
* Is this running on Android?
*/
Q_INVOKABLE
int isIOS()
{
#ifdef Q_OS_IOS
return 1;
#else
return 0;
#endif
}

/**
* @brief isMobile is this on a mobile device?
* @return
*/
Q_INVOKABLE
int isMobile()
{
return isIOS() + isAndroid();
}
....
}
#endif // LIGHTASSISTANT_H

Теоретически вы можете вызвать это в QML как таковой:

import com.lightassistant 1.0
Item {
LightAssistant {
id: la
}

function isIos(){
return la.isIOS();
}

}

Я бы предложил сделать что-то действительно простое, как это, чтобы убедиться, что нет проблем с сантехникой, а затем, если это работает, перейти метод за методом, чтобы увидеть, есть ли другой вызов, который блокирует что-то. Мое лучшее предположение без полного источника — это то, где вы, вероятно, регистрируете компоненты.

2

Другие решения

Других решений пока нет …