Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to communicate between HTML/Javascript and C++ in Qt WebChannel in platform independent way?

For desktops (Windows, Mac, Ubuntu), there is a QWebEngineView and for mobiles (Android, iOS), there is a native QWebView.

Unfortunately, mobiles don't support QWebEngineView.
For example, as discussed in below post:
How to use Qt WebEngine and QWebChannel?
The setWebChannel() is available in QWebEnginePage which is accessible only in QWebEngineView. However, QWebPage doesn't have such method which is accessible in QWebView.

Now, there is another platform independent way, which works on all the platforms, as discussed in Integrating Web Content.
But the example uses QWebChannelAbstractTransport, which can be used only with JSON. Now JSON, due to its over-descriptive nature, could be quite expensive, if the C++ module is sitting somewhere in server and HTML is local; i.e. real client-server communication over internet.
It would have been better, had they use protobuf.

Is there any optimised and platform agnostic way of calling HTML/Javascript from C++ in Qt?

[Note: BTW, current Qt way of calling C++ from Javascript is quite handy using channel.objects and I would like to retain that way.]

like image 510
iammilind Avatar asked Sep 18 '25 23:09

iammilind


1 Answers

With QWebChannel to communicate between C++ and HTML/JS, Qt currently, uses JSON to transport event invocation/data (see QWebChannelAbstractTransport & QWebChannel.js). Over the internet, JSON when compared to Google Protobuf, may be having a overhead of sending field names but this should be negligible compared to 'No data (strings/text) optimization" in either protocols.

Is there any optimised and platform agnostic way of calling HTML/Javascript from C++ in Qt?

The optimized way would be for Qt to provide string/bytes (instead of QJsonObject) in QWebChannelAbstractTransport and JS (both the connection ends) so that we can use custom protocols for transport.

A work around/alternate solution (may not be the optimized way) would be to use the current abstraction to transport using Protobuf/custom protocol like here:

Refer to Qt WebChannel Examples

    In websockettransport.cpp (shared folder in examples)
        C++

        void WebSocketTransport::sendMessage(const QJsonObject &message)
        // Convert message from QJsonObject to Protobuf/custom protocol and
        // use m_socket->sendTextMessage or sendBinaryMessage as required


        void WebSocketTransport::textMessageReceived(const QString &messageData)
        //with QWebSocket::binary[ or text]MessageReceived slot, 
        //convert the message from client (in Protobuf/custom protocol) to 
        //JSON and still
        emit messageReceived(message.object(), this); 

JS: Similarly, since the QWebChannel.js uses socket, need to set the socket to binary or text as required and convert the ProtoBuf/custom protocol message to json as needed by Qt

Simple illustration on using Protobuf (needs all messages to be predefined)/custom protocol in QWebchannel:

C++ -> WebSocketTransport (JSON to Protobuf/custom protocol) -> transmit -> websocket JS (Protobuf/custom protocol to JSON) -> (QWebChannel.js)

JS -> (QWebChannel.js) -> websocket JS (JSON to Protobuf/custom protocol) -> transmit -> WebSocketTransport (Protobuf/custom protocol to JSON) -> C++

Note: JS works on objects (from JSON or any protocol) and may not need conversion as said above; but this needs to be determined.

like image 165
Guru_07 Avatar answered Sep 20 '25 13:09

Guru_07