kui-ffi (0.1.0-alpha.37)
Installation
[registries.forgejo]
index = "sparse+ " # Sparse index
# index = " " # Git
[net]
git-fetch-with-cli = truecargo add [email protected] --registry forgejoAbout this package
kui-ffi
C API for kui: a cdylib plus include/kui.h, and CExtension for loading a C plugin into a Rust host.
kui splits a UI into a model that lays out and paints into a display list (kui-core), a renderer (kui-wgpu) and a windowed runner (kui-native). This crate puts the model, and optionally the runner, behind a flat C ABI: every kui_* function declared in kui.h is exported from libkui_ffi, and the Kui* structs are its repr(C) mirrors. A C, C++ or other-language host links the library and either hands a window to kui_run or drives its own event loop and renderer; a Rust host running kui-native loads a C shared library as a guest extension through CExtension. Strings cross as (ptr, len) UTF-8, values you build are yours until a call consumes them, every entry point catches panics, and a host checks kui_abi_version() against the header's KUI_ABI_VERSION first.
Install
For a Rust host loading C plugins:
cargo add kui-ffi
For a C host, build the library and include the header from the repository:
cargo build -p kui-ffi --release # target/release/libkui_ffi.{so,dylib,dll}
cargo build -p kui-ffi --release --no-default-features # without the windowed runner
The runner feature (on by default) provides kui_run and kui_run_with; a host that owns its own window and renderer turns it off and ships less than half the library.
Example
A C host's frame loop without kui_run (the complete programs are under examples/c/ in the repository):
#include "kui.h"
if (kui_abi_version() != KUI_ABI_VERSION) return 1;
KuiCtx *ctx = kui_ctx_new();
for (;;) {
kui_input_cursor(ctx, mouse_x, mouse_y); /* input, logical px */
KuiEvent ev = KUI_EVENT_INIT;
while (kui_poll_event(ctx, &ev)) { /* read ev.payload with kui_value_get */ }
kui_frame_begin(ctx, width, height, scale); /* build the frame */
KuiSpec root = {.width = {KUI_GROW, 1}, .height = {KUI_GROW, 1}};
kui_root(ctx, &root);
KuiTextStyle big = {.size = 56};
kui_text(ctx, KUI_STR("Hello from C"), &big);
kui_frame_finish(ctx);
KuiDrawData dd = KUI_DRAW_DATA_INIT; /* draw it */
if (kui_draw_data(ctx, &dd)) draw_quads(dd.quads, dd.quad_count, dd.clips);
}
kui_ctx_free(ctx);
A Rust app loading a C plugin:
use kui_ffi::CExtension;
use kui_native::{App, NodeSpec, Ui};
struct Host;
impl App for Host {
fn view(&mut self, ui: &mut Ui<'_>) {
ui.open(NodeSpec::row().fill());
ui.slot("todos/panel"); // the plugin draws here
ui.close();
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let ext = unsafe { CExtension::open("target/debug/panel.so")? };
kui_native::app("host").extension_as("todos", ext).run(Host)
}
Where it fits
| Crate | What it is |
|---|---|
| kui-core | The model: tree, layout, text, display list |
| kui-wgpu | The renderer |
| kui-native | The windowed runner most apps use |
| kui-derive | #[derive(Message)] |
| kui-lua | Lua binding |
| kui-ffi | This crate: the C API |
Documentation
- API reference: https://docs.rs/kui-ffi
- The book: https://kui-book.qxuken.dev
- Repository: https://github.com/qxuken/kui
License
MIT
Dependencies
| ID | Version |
|---|---|
| kui-core | ^0.1.0-alpha.37 |
| kui-native | ^0.1.0-alpha.37 |