将二进制数据从 QML 传递到 C++
Pass binary data from QML to C++
我在 QML 的 JavaScript 中有一个 'binary string',表示我想传递给 C++ 的原始字节(通过已建立的套接字发送)。
我使用的代码是这样的:
// QML
onSomeSignal: {
var proto = new MyMessage(); // https://github.com/dcodeIO/protobuf.js
var bbuf = proto.encode(); // https://github.com/dcodeIO/bytebuffer.js
var bytes = bbuf.toBinary();
messageBridge.send(bytes);
}
// C++
void MessageBridge::send(const QString& data) {
if(m_tcpSocket->state() == QAbstractSocket::ConnectedState) {
m_tcpSocket->write(encodeVarint32(data.length()).toLocal8Bit());
m_tcpSocket->write(data.toLocal8Bit());
}
}
但是,我发现将 JavaScript 字符串转换为 QString 有时会更改字节(可能是因为编码)。
以下代码有效,但效率低下,将字节缓冲区转换为二进制字符串,然后是 JS 数组,转换为 QVariantList,然后零散地填充 QByteArray。
// QML
onSomeSignal: {
var bytes = (new MyMessage()).encode().toBinary();
var bytea = [];
for (var i=bytes.length;i--;) bytea[i] = bytes.charCodeAt(i);
messageBridge.send(bytes);
}
// C++
void MessageBridge::send(const QVariantList& data) {
if(m_tcpSocket->state() == QAbstractSocket::ConnectedState) {
m_tcpSocket->write(encodeVarint32(data.length()).toLocal8Bit());
m_tcpSocket->write(data.toLocal8Bit());
QByteArray bytes(data.length(),'[=13=]');
for (int i=0; i<data.length(); i++) bytes[i] = data[i].toInt();
m_tcpSocket->write(bytes);
}
}
传递 ByteBuffer
or binary string from QML/JavaScript to Qt/C++, in a way that gives me something I can write to a QTcpSocket
的有效方法是什么?
// QML
onSomeSignal: {
var bytes = new MyMessage();
messageBridge.send(bytes.toArrayBuffer());
}
并且数组缓冲区将很好地适合 QByteArray:
// C++
void MessageBridge::send(const QByteBuffer& data) {
if (m_tcpSocket->state() == QAbstractSocket::ConnectedState) {
m_tcpSocket->write(encodeVarint32(data.size()).toLocal8Bit());
m_tcpSocket->write(data);
}
现在请告诉我如何从 C++ 中的 QByteBuffer 转换为 QML 信号中有用的 protobuf.js 对象 :)
Qt 5.7 不理解从 C++ 到 QML 的 QByteArray,因此它只是将其包装到一个不透明的 QVariant 中,使其在 QML 中无用,除了稍后将其传回 C++。
Qt 5.8+ 添加了对 QByteArray 类型的支持。当从 C++ 传递到 QML 时,作为 return 变量或信号参数,QByteArray 被转换为 ArrayBuffer。这对 protobufs 很有用,因为 protobuf 的 javascript API 可以直接解码 ArrayBuffer 类型。
我在 QML 的 JavaScript 中有一个 'binary string',表示我想传递给 C++ 的原始字节(通过已建立的套接字发送)。
我使用的代码是这样的:
// QML
onSomeSignal: {
var proto = new MyMessage(); // https://github.com/dcodeIO/protobuf.js
var bbuf = proto.encode(); // https://github.com/dcodeIO/bytebuffer.js
var bytes = bbuf.toBinary();
messageBridge.send(bytes);
}
// C++
void MessageBridge::send(const QString& data) {
if(m_tcpSocket->state() == QAbstractSocket::ConnectedState) {
m_tcpSocket->write(encodeVarint32(data.length()).toLocal8Bit());
m_tcpSocket->write(data.toLocal8Bit());
}
}
但是,我发现将 JavaScript 字符串转换为 QString 有时会更改字节(可能是因为编码)。
以下代码有效,但效率低下,将字节缓冲区转换为二进制字符串,然后是 JS 数组,转换为 QVariantList,然后零散地填充 QByteArray。
// QML
onSomeSignal: {
var bytes = (new MyMessage()).encode().toBinary();
var bytea = [];
for (var i=bytes.length;i--;) bytea[i] = bytes.charCodeAt(i);
messageBridge.send(bytes);
}
// C++
void MessageBridge::send(const QVariantList& data) {
if(m_tcpSocket->state() == QAbstractSocket::ConnectedState) {
m_tcpSocket->write(encodeVarint32(data.length()).toLocal8Bit());
m_tcpSocket->write(data.toLocal8Bit());
QByteArray bytes(data.length(),'[=13=]');
for (int i=0; i<data.length(); i++) bytes[i] = data[i].toInt();
m_tcpSocket->write(bytes);
}
}
传递 ByteBuffer
or binary string from QML/JavaScript to Qt/C++, in a way that gives me something I can write to a QTcpSocket
的有效方法是什么?
// QML
onSomeSignal: {
var bytes = new MyMessage();
messageBridge.send(bytes.toArrayBuffer());
}
并且数组缓冲区将很好地适合 QByteArray:
// C++
void MessageBridge::send(const QByteBuffer& data) {
if (m_tcpSocket->state() == QAbstractSocket::ConnectedState) {
m_tcpSocket->write(encodeVarint32(data.size()).toLocal8Bit());
m_tcpSocket->write(data);
}
现在请告诉我如何从 C++ 中的 QByteBuffer 转换为 QML 信号中有用的 protobuf.js 对象 :)
Qt 5.7 不理解从 C++ 到 QML 的 QByteArray,因此它只是将其包装到一个不透明的 QVariant 中,使其在 QML 中无用,除了稍后将其传回 C++。
Qt 5.8+ 添加了对 QByteArray 类型的支持。当从 C++ 传递到 QML 时,作为 return 变量或信号参数,QByteArray 被转换为 ArrayBuffer。这对 protobufs 很有用,因为 protobuf 的 javascript API 可以直接解码 ArrayBuffer 类型。