Lean runs main on a helper thread, which Cocoa rejects for video init;
export LEAN_MAIN_USE_THREAD=0 from the justfile on macOS. Wait for the
camera permission event before reading the camera format, since SDL
grants access asynchronously.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The opaque Pixels type wrapped a void* pointing into an SDL_Surface's
pixel buffer, but nothing tied the Pixels lifetime to the surface. If
the GC collected the surface first, the Pixels pointer would dangle,
causing use-after-free.
Replace with two safe alternatives:
- updateTexture now takes a ByteArray (Lean-owned, GC-managed buffer)
plus pitch, matching how Haskell's sdl2 uses ByteString and Rust's
rust-sdl2 uses &[u8]. This is faithful to SDL_UpdateTexture's general
void* interface but requires copying pixels into a ByteArray first.
- updateTextureFromSurface is a new zero-copy convenience that takes an
SDLSurface directly. The C side extracts both pixels and pitch from
the surface internally. Because the surface is borrowed (@&) for the
call's duration, the GC cannot collect it mid-use. This is not
strictly faithful to SDL_UpdateTexture's C API, but is the common
case and avoids an unnecessary memcpy.
Also removes: Pixels type, Pixels.nonemptyType, sdl_pixels_external_class,
sdl_Surface_get_pixels, and the pixels_external_class registration in
sdl_init.
WebcamApp.lean is updated to use updateTextureFromSurface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>