Magnolia exposes a small set of low-level built-ins that let Oak code interact with the host Go runtime and operating system primitives.
This includes:
- Goroutines and channels (
go,make_chan,chan_send,chan_recv) - Runtime metadata (
___runtime_go_version,___runtime_sys_info) - Foreign function calls (
sysproc,syscall) - Thread affinity helpers (
lock_thread,unlock_thread) - Native Win32 loop helper (
win_msg_loop, Windows only) - Raw byte and memory helpers (
bits,addr,pointer,memread,memwrite)
These APIs are powerful and intentionally minimal. They are best used inside thin wrapper libraries for safety and readability.
For a safer wrapper around sysproc and syscall, see lib/sys.oak.
Runs a function on a new goroutine.
ch := make_chan()
go(fn {
chan_send(ch, :ready)
})
evt := chan_recv(ch)
println(evt.data) // :ready
Creates a channel value. If cap is omitted, the channel is unbuffered.
unbuffered := make_chan()
buffered := make_chan(8)
Sends value to ch. If a callback is provided, the operation is coordinated through callback flow.
ch := make_chan(1)
chan_send(ch, 42)
Receives from ch, returning an event object.
Event object shape:
data: received valueok: boolean receive status
ch := make_chan(1)
chan_send(ch, 'hello')
msg := chan_recv(ch)
println(msg.data) // 'hello'
println(msg.ok) // true
Returns the host Go version as a string.
println(___runtime_go_version())
Returns an object with host runtime information.
Common fields include:
osarchcpus
info := ___runtime_sys_info()
println(info.os)
println(info.arch)
println(string(info.cpus))
Resolves a procedure by library and symbol name.
Returns either a proc object or an error object.
proc := sysproc('kernel32.dll', 'GetCurrentProcessId')
if proc.type = :proc -> {
result := syscall(proc)
println(result.type) // :ok or :error
}
Calls a procedure target returned by sysproc (or a numeric address).
Result object shape:
type::okor:error- On success:
r1,r2 - On error:
error
pidProc := sysproc('kernel32.dll', 'GetCurrentProcessId')
res := syscall(pidProc)
if res.type = :ok -> {
println('PID: ' + string(res.r1))
} else {
println('syscall failed: ' + res.error)
}
Pins the current Oak execution to the current OS thread, then releases it.
This is especially important for Win32 UI code, where window creation and message pumping must happen on the same OS thread.
if ___runtime_sys_info().os = 'windows' {
true -> {
lock_thread()
// Create window + run message loop here.
unlock_thread()
}
}
int(...) accepts pointer values and converts them to integer addresses.
Useful when writing pointer-sized values into native struct buffers.
buf := bits([0, 0, 0, 0, 0, 0, 0, 0])
ptr := addr(buf)
n := int(ptr)
println(string(n))
Windows-only helper that runs a native GetMessageW / TranslateMessage /
DispatchMessageW loop for a window handle until exit.
Returns 0 on normal loop exit, or an error object.
if ___runtime_sys_info().os = 'windows' {
true -> {
lock_thread()
// hwnd should be a valid window handle (int/pointer value)
result := win_msg_loop(hwnd)
unlock_thread()
println(string(result))
}
}
Converts between byte list and byte string.
raw := bits([65, 66, 67])
nums := bits(raw) // [65, 66, 67]
addrreturns an address for byte-backed data.pointerconverts integers, atom references, pointers, and byte strings into pointer values.
buf := bits([65, 66, 67])
ptr := pointer(addr(buf))
Reads length bytes from memory and returns a byte string.
Writes byte data to memory. Data can be a byte string, atom, or byte list.
buf := bits([65, 66, 67])
ptr := addr(buf)
memwrite(ptr + 1, bits([90]))
println(bits(memread(ptr, 3))) // [65, 90, 67]
// Named references are also writable
memwrite(:slot, :hello)
println(name(pointer(:slot))) // :hello
- Avoid arbitrary memory addresses. Invalid reads/writes can crash the process.
- Keep buffers alive while passing pointers to native calls.
- Prefer passing explicit byte strings for pointer-backed arguments.
- Treat
syscallboundaries as unsafe code and validate all arguments. - Consider wrapping low-level calls in library APIs (for example,
gpu) instead of direct use in app code.
See samples/go-interop.oak for a runnable example that combines:
- goroutine + channel coordination
- runtime metadata
- safe
sysproc/syscallinvocation vialib/sys.oak - direct memory read/write on a byte buffer