Extern Functions

Binding C functions into Chasm with extern fn declarations.

extern fn declares a C function so Chasm code can call it. The compiler emits a direct call to the C symbol at the call site, no marshaling, no overhead.

Syntax

extern fn draw_circle(x: float, y: float, r: float, color: int) -> void

The parameter names are for documentation only. The types map directly to C:

Chasm typeC type
intint64_t
floatdouble
boolbool
stringconst char*
voidvoid

C Name Alias

If the C symbol name differs from what you want to call it in Chasm, use = "c_name":

extern fn draw_circle(x: float, y: float, r: float, color: int) -> void = "rl_draw_circle"

Now Chasm calls it as draw_circle(...) but the emitted C calls rl_draw_circle(...). Without an alias, the Chasm name is used as the C symbol directly.

Calling Extern Functions

Extern functions are called like any other function:

extern fn draw_text(text: string, x: int, y: int, size: int, color: int) -> void

def on_draw() do
  draw_text("Score: #{@score}", 10, 10, 20, 0xffffffff)
end

Engine Bindings

When you compile with --engine raylib, the Raylib binding file is prepended automatically. It declares all Raylib functions as extern fn:

# From engine/raylib/raylib.chasm (included automatically)
extern fn draw_rectangle(x: float, y: float, w: float, h: float, color: int) -> void
extern fn draw_circle_v(cx: float, cy: float, r: float, color: int) -> void
extern fn key_down(key: atom) -> bool
extern fn key_pressed(key: atom) -> bool

Your game script then calls them directly:

def on_draw() do
  draw_rectangle(@player_x, @player_y, 32.0, 32.0, 0x4488ffff)
  draw_circle_v(@bullet_x, @bullet_y, 4.0, 0xffff00ff)
end

Godot Plugin

When compiling with --engine godot, the GDExtension binding is used instead. Chasm scripts become ChasmComponent nodes that can be attached to any Godot node.

Writing Your Own Engine Bindings

Create a .chasm file with extern fn declarations for every C function you want to expose:

engine/my_engine.chasm:

extern fn draw_sprite(id: int, x: float, y: float, w: float, h: float) -> void = "engine_draw_sprite"
extern fn play_sound(id: int, vol: float) -> void = "engine_play_sound"
extern fn load_texture(path: string) -> int = "engine_load_texture"

Then pass it to the CLI as a prelude using resolveImports in a custom CLI wrapper, or include it via import in your game file.

Type safety:

Extern functions bypass the type checker at the boundary. Ensure parameter types in the Chasm declaration match the C function signature exactly.