This repository contains source code of the following Rust library crates:
- sokol (README) - Rust bindings to the sokol header-only, cross-platform libraries.
- sokol-imgui (README) - Rust bindings to the
- sokol-sys (README) - system crate to compile native dependencies shared by other crates.
To complement the crates above:
- sokol-stb - a library for easy access to a subset of the stb libraries.
- sokol-samples - a number of examples ported from sokol-samples.
How to build
The current version compiles (and has been tested) with stable Rust (v1.34.1) on Windows (both MSVC and GNU toolchains), MacOS and Linux.
> git clone --recursive https://github.com/code-disaster/sokol-rs > cd sokol-rs > cargo build
sokol-samples folder contains some examples ported from sokol-samples/sapp.
> cargo run --bin clear-sapp
About the implementation
The SApp program loop
In the C version of
sokol_app, when compiled with
SOKOL_NO_ENTRY, you call
sapp_run(), passing callback function pointers for setup, frame updates, and cleanup.
In the Rust version, you call
sokol::app::sapp_run(). This hands over control to the C library, which then will operate as usual. The C callbacks are implemented by sokol-rs. They are forwarded to your application via the
SApp trait. User applications implement this trait to power the application loop.
Check the clear-sapp sample for a minimal implementation.
API style and implementation details
I tried to stay as close as possible to the source, while adjusting to the Rust naming conventions, as well as making the public API more convenient in places a direct port would be too cumbersome.
- Function names stay the same. No change here.
- Function signatures are identical most of the time. In some rare cases, I moved parameters out of structs and pass them as additional function parameters.
- Type names are renamed, e.g.
- Some identifiers, like "type", had to be renamed because they clash with reserved keywords in Rust.
- Element names in enums are shortened and changed to CamelCase, e.g.
SAppEventType::Resized. On the plus side, they are all totally type-safe now.
- I tried to stay true to the C99-style struct initializers - check the samples to see what it looks like. Since Rust forces you to initialize all struct members, most of them enable
#[derive(Default)]so that you are still able to only set the options you are interested in - everything else can be initialized to sokol's default values with
- Arrays in structs, which are all fixed-sized in sokol, are initialized using
Vec<T>in public declarations. This is because they can be set conveniently with
vec!, so you don't have to keep an eye on the array size, and/or spatter
Default::default()all over the place. (I tried to be clever and use macro magic to make this part even more convenient while not paying the Vec<> allocation overhead, but I'm not nearly clever enough with Rust... yet.)
In the Rust library, the
audio modules are not as separable as their C counterparts. Essentially, sokol-rs assumes that you use them in conjunction.
appfunctions to configure the render backend.
saudio_setup()is told to use callbacks, the function callback is part of the
SApptrait (and, as a matter of fact, managed by the
appmodule in most parts).
The following libraries are implemented:
|sokol_args.h||n/a||n/a||low priority: there are many cmdline parsers for Rust already|
||done||callback API via trait in
||mostly done||trace hooks are enabled (and consumed by the
missing: separate resource management, render contexts, user-provided buffers
Additionally, some utility libraries are available:
|sokol_gl.h||n/a||n/a||no plans yet|
gfxis configured to use the "native" render API on each platform:
- Windows (MSVC): Direct3D 11
- Windows (not MSVC, tested with
x86_64-pc-windows-gnu): OpenGL 3.3
- MacOS: Metal
- Linux: OpenGL 3.3
x86_64-pc-windows-gnuuses GL33 because sokol_gfx fails to compile for Direct3D 11 with gcc on MinGW64. I didn't invest much time to figure out why.