Native presentation library
Usage guide of libgfpresent: the C interface that runs the presentation module of every kit as native code for a native host, with the same bytes as the web modules.
Presentation modules as a native library (libgfpresent) #
What it is for #
Every kit that draws something (a HUD, a camera, an effect) has a presentation module: a small program that is given what the game state looks like and answers what to draw. On the web these modules are loaded as .wasm files. libgfpresent is the same modules compiled to native code, in one library, for hosts that are not a browser: the C kit host, the Godot, Unity and Unreal wrappers and the desktop player. The library answers the same bytes as the .wasm of the web, so a kit looks the same on every engine.
It only computes. Drawing the answer is the job of the engine adapter.
Install #
You do not build it to use a game: the wrappers and the desktop player ship it. To build it yourself:
cd wrappers/present-native && cargo build --locked --release
The result is libgfpresent (shared) in target/release/.
First example #
<!-- test: wrappers/present-native/tests/c_api.rs::every_listed_module_can_be_made_and_declares_its_own_kit_in_its_needs --> List the kits that have a module, create one and ask what it needs:
uint32_t abi = gfp_abi(); /* the present ABI the modules speak */
for (uint32_t i = 0; i < gfp_count(); i++) {
const char *kit = gfp_kit(i); /* e.g. "combat.core" */
GfpModule *m = gfp_create((const uint8_t *)kit, strlen(kit));
if (!m) continue; /* NULL: no module for that kit */
const uint8_t *out; size_t len;
if (gfp_needs(m, &out, &len) == 0) {
/* out[0..len] is the module's declaration of what it needs, as postcard bytes */
}
gfp_free(m);
}
C interface #
Bytes in and out are postcard, exactly like the .wasm exports gf_needs, gf_init and gf_frame.
| Function | Role |
|---|---|
gfp_abi() | The present ABI version these modules speak. |
gfp_count() | The number of kits that have a module. |
gfp_kit(index) | The kit id at that index, as a C string; NULL past the end. |
gfp_create(kit, len) | A module for the kit id (UTF-8, matched exactly); NULL when there is none. |
gfp_needs(m, &out, &out_len) | What the module needs from the host. |
gfp_init(m, in, len, &out, &out_len) | Starts the module with its configuration. |
gfp_frame(m, in, len, &out, &out_len) | One frame: the state in, the drawing commands out. |
gfp_input(m, in, len, &out, &out_len) | One input event of the window, for a module that draws an interface surface (ABI 1.5). |
gfp_free(m) | Releases the module. |
Rules:
- A call answers 0 when it worked and 1 when the module panicked: leave that module out.
gfp_inputanswers 2 for a module that takes no input. outstays valid until the next call on the same module; copy it if you need it longer.- A module belongs to one thread at a time.
- The kit names are those of the kits (
combat.core,hud.action…); an unknown name, an empty name or one that is not text gives NULL.
When it does not do what you expect #
gfp_createreturns NULL: that kit has no presentation module, or the name is not exact (case and spaces count).- A module answers 1: it panicked. Stop calling it and run the game without its presentation.
- The answer differs from the web: it should not. The library is checked byte for byte against the
.wasmmodules; report the kit and the input.
Limits #
- It draws nothing and loads no files; the engine adapter draws the answers.
- There is no
.wasminterpreter inside: native hosts use this library, web hosts use the.wasmfiles. - Using the Rust crate directly takes the features of your own build; the C library is the one that is proved identical.
Versions #
Library 0.2, present ABI 1 (with the input entry from 1.5).