WebXR in C++
~ 3.5 Minute Read.
Web XR in C++… what?
I recently had the joy of linking javascript to C++ code for a tiny game we’re building at Vhite Rabbit.
Compilers like Emscripten or cheerp – which I didn’t get a chance to try just yet – allow you to compile your C++ or C code to ASM.js or WebAssembly. Since you will want access to some Web APIs, you will need to link some javascript to your WASM code.
Let’s get into some more technical details for those who are interested:
Linking JS in CMake
For emscripten you can check the documentation here. While that page and the libraries that come with emscripten should get you all the way there, I thought it may be helpful to give a overview anyway. With a header like:
#ifndef WEBXR_H_ #define WEBXR_H_ #ifdef __cplusplus extern "C" { #endif /** Init WebXR rendering */ extern void init_webxr(/* ... */); #ifdef __cplusplus } #endif #endif
You can link the implementing javascript library:
mergeInto(LibraryManager.library, { init_webxr: function(/* ... */) { } );
… super easily by adding appropriate CMake flags:
if(CORRADE_TARGET_EMSCRIPTEN) # "link" the webxr javascript library set_property(TARGET your-target APPEND_STRING PROPERTY LINK_FLAGS " --js-library library_webxr.js") endif()
Where CORRADE_TARGET_EMSCRIPTEN
is a flag provided by Corrade. This
works without, if you want to unconditionally link the js, though.
I use the toolchains
that are also used in Magnum.
Additionally I recommend adding proper debug flags:
# Some handy debug flags set_property(TARGET your-target APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " -s ASSERTIONS=1 -s DEMANGLE_SUPPORT=1")
Working with the heap
To pass data between C++ and JS with emscripten, you will want to use the heap. While passing smaller data via function arguments and return values is trivial, you can pass entire structures by allocating heap memory:
var yourStruct = Module._malloc(SIZEOF_YOUR_STRUCT);
To then set its values using setValue 3:
setValue(yourStruct + 0, 42.0, 'double') setValue(yourStruct + 8, 42.0, 'float') setValue(yourStruct + 12, 42, 'i64') setValue(yourStruct + 20, 42, 'i32') setValue(yourStruct + 24, 42, 'i16') setValue(yourStruct + 28, 42, 'i8')
Finally, passing the pointer and if you’re done using that heap memory, you should be deallocating it either in javascript:
Module._free(yourStruct);
or in C/C++ as you would usually do (I hope).
I hope this helps someone out there, I know it would have saved be a minute to have this a little more condensed and in one place.
- 1
- This will probably be a blog post of its own sometime.
- 2
- I just noticed it’s missing an origin trial token may not run!
- 3
- In emscripten’s libraries you will often see
makeSetValue
, which is meant to work with the JSON library which stores the offsets of the members of all the C structs, though.
Written in 60 minutes, edited in 5 minutes.