问题
I have a 'binary string' in JavaScript inside of QML, representing raw bytes that I want to pass to C++ (to send over an established socket).
I was using code like this:
// 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());
}
}
However, I discovered that translating the JavaScript string to a QString was sometimes changing the bytes (presumably because of encodings).
The following code works, but it's inefficient, converting the byte buffer to a binary string, then a JS array, converting to a QVariantList and then piecemeal populating a 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(),'\0');
for (int i=0; i<data.length(); i++) bytes[i] = data[i].toInt();
m_tcpSocket->write(bytes);
}
}
What is an efficient way to pass either a ByteBuffer or binary string from QML/JavaScript to Qt/C++, in a way that gives me something I can write to a QTcpSocket?
回答1:
// QML
onSomeSignal: {
var bytes = new MyMessage();
messageBridge.send(bytes.toArrayBuffer());
}
and the array buffer will nicely fit into a 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);
}
Now please tell me how to go the other way from a QByteBuffer in C++ to a useful protobuf.js object in a QML signal :)
回答2:
Qt 5.7 does not understand QByteArray from C++ to QML, so it just wraps it into an opaque QVariant, making it useless in QML, except for passing it back into C++ at a later time.
Qt 5.8+ adds support for QByteArray type. When passed from C++ to QML, either as a return variable or a signal parameter, the QByteArray is converted to an ArrayBuffer. This is useful for protobufs, as the protobuf's javascript API can directly decode an ArrayBuffer type.
来源:https://stackoverflow.com/questions/40940199/pass-binary-data-from-qml-to-c