kui-ffi 0.1.0-alpha.49

C API for kui (cdylib, staticlib on request, + include/kui.h)
Documentation
# 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:

```sh
cargo add kui-ffi
```

For a C host, build the library and include the header from the repository:

```sh
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):

```c
#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:

```rust
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](https://crates.io/crates/kui-core) | The model: tree, layout, text, display list |
| [kui-wgpu](https://crates.io/crates/kui-wgpu) | The renderer |
| [kui-native](https://crates.io/crates/kui-native) | The windowed runner most apps use |
| [kui-derive](https://crates.io/crates/kui-derive) | `#[derive(Message)]` |
| [kui-lua](https://crates.io/crates/kui-lua) | Lua binding |
| [kui-ffi](https://crates.io/crates/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