Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RAII and resources

Every raylib resource in raylib-rs is a Rust struct that cleans up on drop. The Unload* family of C functions is never exposed in the public API — Drop implementations call them automatically when the resource leaves scope. This eliminates the class of bug where a resource is forgotten or freed twice.

The pattern applies uniformly: Image, Texture2D, RenderTexture2D, Font, Mesh, Shader, Material, and Model all implement Drop. You allocate with load_* or gen_image_*; you free by letting the value go out of scope (or by calling drop() explicitly when order matters).

API surface

  • Image — CPU-side pixel buffer; dropped by calling UnloadImage.
  • Texture2D — GPU texture handle; dropped by calling UnloadTexture.
  • RenderTexture2D — off-screen render target; dropped by UnloadRenderTexture.
  • Font — loaded font; dropped by UnloadFont.
  • Mesh — vertex data; owned by Model (do not drop separately).
  • Shader — GPU shader program; dropped by UnloadShader.
  • Material — material parameters; owned by Model.
  • Model — 3D model including meshes and materials; dropped by UnloadModel.
  • ModelAnimations — new in 6.0, RAII wrapper for the skeletal-animation animation set.

Example

The example below shows resource loading and explicit teardown order. image is dropped first; font is kept alive until the end of the outer scope. Because Drop is deterministic in Rust, the sequence is predictable and correct.

extern crate raylib;
use raylib::prelude::*;

fn main() {
    let (mut rl, thread) = raylib::init()
        .size(640, 480)
        .title("RAII demo")
        .build();

    // gen_image_color returns an Image that owns its pixel buffer.
    let image = Image::gen_image_color(64, 64, Color::RED);

    // load_texture_from_image uploads to the GPU.
    let texture = rl.load_texture_from_image(&thread, &image).unwrap();

    // Explicit drop: image is freed here (UnloadImage called).
    // texture remains alive.
    drop(image);

    // texture is freed here when it leaves scope (UnloadTexture called).
    drop(texture);

    // RaylibHandle (rl) is freed here, tearing down the window.
}

Gotchas

  • Lifetime-bound audio resourcesWave, Sound, Music, and AudioStream are bound by lifetime to a RaylibAudio. They cannot outlive the audio device. See the audio chapter.
  • raylib-allocated buffers — functions that return raylib-managed byte slices (e.g., exported image data) wrap them as ManuallyDrop<Box<[T]>> and free via the matching Unload* or MemFree call — never libc::free. This stays correct under custom raylib allocators. See DECISIONS.md for the rationale.
  • Model owns its Mesh and Material arrays — do not call drop() on a Mesh or Material that came from a Model. Dropping the Model handles everything.

See also