Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sdl

SDL2 bindings for Milo. Video, input, gamepad, and audio.

milo add github.com/milo-language/milo-sdl            # latest release
milo add github.com/milo-language/milo-sdl@v0.1.0     # or pin a tag
from "sdl" import {
    SDL_Init, SDL_Quit, SDL_CreateWindow, SDL_CreateRenderer, SDL_CreateTexture,
    SDL_UpdateTexture, SDL_RenderClear, SDL_RenderCopy, SDL_RenderPresent,
    SDL_INIT_VIDEO, SDL_WINDOWPOS_CENTERED, SDL_WINDOW_SHOWN,
    SDL_TEXTUREACCESS_STREAMING, SDL_PIXELFORMAT_ABGR8888,
}

let W: i64 = 320
let H: i64 = 240

fn main(): i32 {
    unsafe {
        SDL_Init(SDL_INIT_VIDEO)
        let win = SDL_CreateWindow("demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                   W as i32, H as i32, SDL_WINDOW_SHOWN)
        let ren = SDL_CreateRenderer(win, -1, 0)
        let tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ABGR8888,
                                    SDL_TEXTUREACCESS_STREAMING, W as i32, H as i32)

        var fb: Vec<u32> = Vec.new()
        for i in 0..(W * H) { fb.push(0xFF102030) }

        SDL_UpdateTexture(tex, 0 as *u8, fb.ptr() as *u8, (W * 4) as i32)
        SDL_RenderClear(ren)
        SDL_RenderCopy(ren, tex, 0 as *u8, 0 as *u8)
        SDL_RenderPresent(ren)
        SDL_Quit()
    }
    return 0
}

Bindings, not a framework

This package is the extern declarations and the constants — nothing else. No Window type, no Drop impls, no frame-loop helper, no opinion about how you poll input. Those choices differ per project and are cheap to write; the declarations are what everybody was retyping.

Modules

Import Contents
"sdl" init/quit, window, renderer, texture, events, keyboard, mouse, timing
"sdl/keys" USB HID scancodes — what SDL_GetKeyboardState is indexed by
"sdl/gamepad" GameController API, buttons, hotplug events
"sdl/audio" queue-API audio device and SDL_AudioSpec

Everything is checked against the real headers

Each extern fn carries @cSig and each constant carries @cValue, so the whole surface is verified against SDL's own headers at build time:

error[c-decl]: a declaration does not match the C header it claims to describe
  sdl$SC_W: Milo says 27, SDL2/SDL.h defines SDL_SCANCODE_W as something else

This is not hypothetical. Writing this package turned up a real mismatch on the first build: SDL_IsGameController returns SDL_bool, an enum whose enumerators are both non-negative — so C gives it an unsigned underlying type. Every hand-written copy of that declaration across our own projects said i32.

You do not need SDL's headers to build. Milo links SDL by name. If the headers are absent — a machine with libSDL2 but not libsdl2-dev — the guards announce that they are skipping and the build proceeds:

warning: @cLayout/@cSig/@cValue guards skipped — 'SDL2/SDL.h' is not installed,
so there is no header to check these declarations against

Requires Milo 0.1.0 or newer for @cValue.

Installing SDL2

brew install sdl2                 # macOS
apt install libsdl2-dev           # Debian/Ubuntu

Homebrew's sdl2 formula now installs sdl2-compat, an SDL2 API layer over SDL3. The bindings here are ABI-compatible with it and the constants verify identically, so nothing in this package cares — but it explains why sdl2-config --version may report an SDL3 build underneath.

Header discovery for the build-time guards goes through pkg-config --cflags sdl2.

Two things the signatures do not tell you

Ask for the subsystems you will use. Leaving SDL_INIT_AUDIO out of SDL_Init does not error — SDL_OpenAudioDevice just returns 0, so every sound is a silent no-op and the program otherwise runs perfectly. This cost one of our games its entire soundtrack.

SDL_QueueAudio appends, it does not mix. Music and effects on one device serialise: an effect waits behind everything already queued before it is audible. Open a second device and let the OS mixer do the mixing.

Pointers

SDL_Window*, SDL_Renderer* and SDL_Texture* are all *u8 here — Milo has no opaque handle type in an extern position, so nothing stops you passing one where another is wanted. Keep them in named variables and the mistake is hard to make.

License

MIT

About

SDL2 bindings for Milo — video, input, gamepad, audio

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors