模块[]未安装--正在注册自定义C++;QML的包装器 我需要访问一个C++ API来处理CAN总线。看起来最好的解决方案是编写一个QML包装器来公开我需要的所有功能
这是我迄今为止的模块[]未安装--正在注册自定义C++;QML的包装器 我需要访问一个C++ API来处理CAN总线。看起来最好的解决方案是编写一个QML包装器来公开我需要的所有功能,c++,qt,qml,qt-creator,app-manager,C++,Qt,Qml,Qt Creator,App Manager,这是我迄今为止的canservice.cpp: #include "canservice.h" #include <QCanBus> #include <QDebug> #include <QCanBusFrame> #include <QTimer> #include <QtCore/qbytearray.h> #include <QtCore/qvariant.h> #include <QtCore/qdebug
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);
}
在我的QML文件中,我首先尝试导入新定义的服务:import can.myapp 1.0
,然后声明它的一个实例:
CANService {
id: "myCanService"
}
当我尝试运行此应用程序并加载调用CANService
的QML文件时,它没有加载,并且在应用程序控制台中出现以下错误:
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
的正确位置在哪里 我之所以回复,是因为您将一篇旧文章标记为类似内容
这里有几个问题:
1) 您在哪里调用qmlRegisterType(“can.myapp”,1,0,“CANService”)
我的理解是,在实例化QtQuickApplicationViewer
之前,需要在main
方法中调用它(如果以这种方式加载的话)
2) 这是否适用于简单的示例(将简单的QString
值传递给函数)
目前我并没有积极使用Qt进行编码,但希望这能为您指明正确的方向:
下面是我的一个应用程序的“main”方法,它使用自定义组件(通过命令行实现简单的Java连接)
我建议做一些非常简单的事情,像这样,以确保管道没有问题,然后,如果可行的话,逐个方法,看看是否有另一个调用阻塞了某些内容。在没有完整来源的情况下,我的最佳猜测是,它可能是您注册组件的地方。我之所以回复,是因为您将一篇旧文章标记为类似内容 这里有几个问题: 1) 您在哪里调用
qmlRegisterType(“can.myapp”,1,0,“CANService”)
我的理解是,在实例化QtQuickApplicationViewer
之前,需要在main
方法中调用它(如果以这种方式加载的话)
2) 这是否适用于简单的示例(将简单的QString
值传递给函数)
目前我并没有积极使用Qt进行编码,但希望这能为您指明正确的方向:
下面是我的一个应用程序的“main”方法,它使用自定义组件(通过命令行实现简单的Java连接)
我建议做一些非常简单的事情,像这样,以确保管道没有问题,然后,如果可行的话,逐个方法,看看是否有另一个调用阻塞了某些内容。在没有完整来源的情况下,我的最佳猜测是,它可能是您注册组件的地方。谢谢您的回复。我想你是对的,我把
qmlRegisterType…
放在头文件中,这似乎不正确。但是由于我使用的是appman
,所以我的应用程序没有main
方法。你知道我可以在哪里注册吗?@Aras我对appman感到困惑,因为我从未使用过它。我会尝试任何initialize
方法,看看您是否可以在QML查看器启动之前加载,但除非这样,否则我会直接联系开发人员,看看他们是否可以给您一个钩子来绑定它。祝你好运我通常在他们的*.cpp
文件中注册:const int registration=qmlRegisterType
。这些变量是在执行main()
之前创建的。有点危险,但还没有遇到任何问题。谢谢您的回复。我想你是对的,我把qmlRegisterType…
放在头文件中,这似乎不正确。但是由于我使用的是appman
,所以我的应用程序没有main
方法。你知道我可以在哪里注册吗?@Aras我对appman感到困惑,因为我从未使用过它。我会尝试任何initialize
方法,看看您是否可以在QML查看器启动之前加载,但除非这样,否则我会直接联系开发人员,看看他们是否可以给您一个钩子来绑定它。祝你好运我通常在他们的*.cpp
文件中注册:const int registration=qmlRegisterType
。这些变量是在执行main()
之前创建的。有点危险,但还没有任何问题。这可能会让你感兴趣。这可能会让你感兴趣
component not ready:
"file:///home/aras/Projects/myapp/apps/com.myapp.diagnostics/Diagnostics.qml:5 module \"can.myapp\" is not installed\n"
#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();
}
#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
import com.lightassistant 1.0
Item {
LightAssistant {
id: la
}
function isIos(){
return la.isIOS();
}
}