parro-it/libui-node

WebAssembly

brandonros opened this issue · 14 comments

Is it possible to make a compile target a WebAssembly module so that code that compiles down to WebAssembly could then create native GUIs?

It should be easy enough to wrap this in an API that can be exposed to WASM.

It should probably be a separate module, though.

I'm confused as to where to start on this. Should I compile https://github.com/andlabs/libui to a WASM module, or can we change binding.gyp in this repo (https://github.com/parro-it/libui-node) to output a WASM module?

I suggest starting by making a basic node module that exposes an API to WASM, maybe a way to console.log to start.

From there you should have your node module expose APIs for creating UI elements and slowly build up what it can do.

Alternately you might want to ditch Node altogether and look into something like Wasmtime and see what they have for C++ library integration.

Yeah! I'm not sure if the API is enough to run GUI libraries though. I'm pretty sure libui needs headers that are platform-specific which wouldn't be covered.

I feel like the reason nobody has done this yet is because it isn't a good idea.

Why not just write node.js then bundle the run time with your "native" application, instead of involving WASM runtimes + modules?

What are your thoughts?

Yeah, I'm not sure. I can see the benefit of extending WASI-style applications with APIs for user interfaces.

I think the Node.js approach would be a lot easier in the end, actually. I'm not sure how flexible WASI is for adding new native APIs.

Not only that, how would it stack up to something of the likes of https://github.com/microsoft/react-native-windows?

Help me understand this: how would you write WebAssembly to call say.. a Win32 API function like this? https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowa

WASI exposes these functions: https://gist.githubusercontent.com/syrusakbary/3b518e870128602eae667527d3aaa842/raw/89ee3c35b7485e995ab7220779b3308d7bf236b7/wasi.wat

Unless I am mistaken, it isn't actually possible to call any system libraries?

It would have to be outside of WASI. Then you create bindings to WASI to access this new API.

I'm 99% sure it wouldn't work, here's why:

https://00f.net/2019/04/07/compiling-to-webassembly-with-llvm-and-clang/

When you try to use clang to compile this C code to WASM output, I think it'll fail on the #include.

/*
  gcc -c -o messagebox.o \\VBOXSRV\Downloads\wasm\messagebox.c && gcc -o messagebox.dll -s -shared messagebox.o -Wl,--kill-at,--subsystem,windows
*/

#include <windows.h>

#define EXPORT __stdcall __declspec(dllexport)

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD dwReason, LPVOID lpvReserved) {
  switch (dwReason) {
    case DLL_PROCESS_ATTACH: {
      MessageBox(
          NULL,
          "Resource not available\nDo you want to try again?",
          "Account Details",
          MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2
      );
      break;
    }
  }
  return TRUE;
}

emscripten-core/emsdk#153

Any ideas how to get around that?

Yeah, you need to build libui's C++ libraries into the runtime and then have the runtime expose it to WASM modules somehow.

Alright, I'll close this as "basically impossible at the moment given the fact that the runtimes/WASI/bindings only really support a very small subset of Windows functionality, aka not enough to actually call UI methods/APIs"

Thank you for all of your help.