Skip to content
r0ller edited this page Apr 14, 2021 · 23 revisions

This is a sketch for a cross-platform architecture where the frontend is qml and the backend is c++. I know that qt is cross-platform by design but I was looking for a design with which I can have the same frontend and backend everywhere even in a client-server setup. So I started by decoupling the qml ui and looked for a design pattern with which the communication can be solved in each scenario. Finally, I chose the command design pattern and the scenarios are as follows:

  • native (desktop): has normal qml ui which if necessary (say on click of a button), passes a command object (stringified json object) to an exposed method which passes it on to the backend. The backend here is a library that exports a function that receives the command and returns the response. The library itself implements the rest of the command design pattern. The response is returned to the ui by invoking a qml method.

  • android: has a webassembly build of the same qml ui in a webview that passes the command json object via webmessage channel through the webview to the android java layer which passes it on to the c++ backend library via java native interface. The backend is the same c++ library but crosscompiled for android. The response is returned to the qml ui via webmessage channel. In this case only an android wrapper app is necessary that handles a webview for the ui and handles the "backend" calls. Theoretically, the same can be done on iOS as safari has the webmessage channel concept as well but I'm not familiar with that platform at all.

  • browser: I have not tried this yet but this I expect to be a simple webassembly build of the native version.

  • nodejs: has a webassembly build of the same qml ui which is loaded on a GET request from the nodejs server. When necessary, the qml ui posts a command json object in a request to the appropriate endpoint of the nodejs server where the request is handled and the command json object is passed on to either a webassembly build of the backend library or a nodejs N-API C++ addon that wraps the backend logic. The response is then returned to the client from nodejs and then to the qml ui either via the webassembly built qml method invocation or via emscripten inline javascript.

As this is currently just a sketch and there's no real command json object sent (and no command design pattern in place) when you click on the text "Hello world" only some test strings are sent like "Hello from QML" to backend and the response is "Returned from backend: Hello from QML".

All builds are debug builds without any optimization so the android app load time is damn slow but afterwards it works just like the native one. I have not yet tweaked the project file so you need to comment/uncomment a few defines in the qmlwasm1 project file configuration to get a successful webassembly or native build. The following three defines determine the build:

__ANDROID__
__NODEJS__
__NATIVE__

The main parts of the repo are:

  • qmlwasm1: contains the qml ui logic (depends on qwa_pure_backend when compiled for native)
  • qwa_pure_backend: contains the backend logic. Building the qwa_pure_backend was not smooth as the project file settings did not make it to the effective qmake call so there's a manual_build.sh in the build-qwa_pure_backend-Debug directory.
  • Android/qmlwasm1: contains a full integration of the ui and backend in an android app
  • qwa_backend: qt library variant of qwa_pure_backend but it does not work (yet) on android for whatever reasons
Clone this wiki locally