Qt Everywhere: WebAssembly and WebGL streaming
Qt Everywhere - this is how Qt source archives are named. At 5.12.0, WebAssembly and WebGL streaming are delivered and everywhere sounds different. So I asked for something to prototype. A prototype chat on web sockets was quickly thrown in to test network support. Under the cut there will be an instruction for building and running a project on WebAssembly, an example of invoking JavaScript from C ++.
Building Qt with WebAsse Assembly
First you need to put the toolchain emscripten , which will collect Qt. Do not forget to write the environment variables that qmake would find emcc. The script was configure
run with the following parameters:
./configure \
-prefix /home/dmitry/Qt/5.12.0/wasm \
-xplatform wasm-emscripten \
-confirm-license -opensource \
-nomake tests \
-c++std c++1z \
-nomake examples \
-release \
-no-dbus \
-skip qtxmlpatterns \
-skip qttools
Further, as elsewhere:
$ make
$ make install
Build and run the project
$ ~/Qt/5.12.0/wasm/bin/qmake
$ make
$ emrun chat.html
Platform specific code
Sewing the url on which the backend is hanging is not very good, because want to run on an arbitrary port. In the case of work from the browser, you need to take location.hostname
and location.port
to determine where the backend is running. This will have a little pee on JavaScript.
For fans of defines there Q_OS_WASM
, I prefer to put the code in pimpl and separate files. Pimpl is superfluous here, but the code will be spread to different files
Let's get some config
//config.h#pragma once#include<QtCore/QUrl>classConfig
{public:
static QUrl wsUrl();
};
and two implementations
//config.cpp#include<QtCore/QCoreApplication>#include<QtCore/QCommandLineParser>#include"config.h"
QUrl Config::wsUrl()
{
QCommandLineParser parser;
QCommandLineOption wsOption(QStringList() << "u" << "url"
, "WebSocket url"
, "url"
, "ws://localhost:1234");
parser.addOption(wsOption);
parser.process(*QCoreApplication::instance());
return QUrl(parser.value(wsOption));
}
//config_wasm.cpp#include<QtCore/QByteArray>#include<emscripten/emscripten.h>#include<emscripten/html5.h>#include"config.h"
QUrl Config::wsUrl()
{
QByteArray buff(1024, 0);
EM_ASM_({
var url = "ws://"+ window.location.hostname + ":" + window.location.port + "/ws";
stringToUTF8(url, $0, $1);
}, buff.data(), buff.size());
return QUrl(QString::fromUtf8(buff));
}
It remains to register in the pro file
wasm {
SOURCES += config_wasm.cpp
} else {
SOURCES += config.cpp
}
EM_ASM_
This is the emscripten magic that allows you to call JavaScript code from C ++. Although it could be done without JavaScript
emscripten::val location = emscripten::val::global("location");
auto host = QString::fromStdString(location["host"].as<string>());
auto protocol = QString::fromStdString(location["protocol"].as<string>());
Browser support
Desktop browsers: runs and works in Сhrome, Firefox, Safari, Edge (here it was necessary to enable the experimental functions of JavaScript). Depending on the hardware, there may be significant delays in compiling WebAssembly.
In Chrome, Andorid can take minutes to compile WebAssembly. Immediately noticed the lack of support for mobile browsers, namely, there is no calling the system keyboard, when trying to enter text.
Safari on iOS 12 here the application crashes at the WebAssembly compilation stage and I did not debug. Theoretically, you can go to asm.js, but this requires a separate study.
Qt Quick WebGL
The blog positioned as VNC on web sockets with rendering on WebGL. From Qt WebSockets and Qt dependencies compiled with OpenGL ES 2 support i. drive on hardware without a GPU will be painful. To support it, it is enough to put Qt WebGL Streaming Plugin in the online installer and run the application with the parameter -platform webgl
or -platform webgl:port=80
, if you need to specify the port.
But this technology has its limitations:
- delays or notorious input lag;
- There is no support for Qt Widgets;
- lack of sound transmission;
- one user connection per process i. In the second tab, no longer go, the preloader will spin.
I also noticed a drop in fps during StackView animation on transitions between screens. The dignity of WebGL streaming:
- built-in server;
- minimum of effort. I did not have to compile from Qt sources and rebuild an existing application separately.
Ways to use WebAssembly and WebGL Streaming
Alternative to Wt when there is a ready application in C ++ and you need to fasten a web interface to it. For example web-interface to torrent rocking.
Web interface for some smart home. Not for nothing in MQTT in Qt, and on msorvig / qt-webassembly-examples an example of mqtt_simpleclient . You can have a common UI code that works on the tablet and in the browser.
The code is available on GitHub , prepared binaries in the same place