Part 24: Platform
Under every Rux program sits an operating system, full of functions written in C long before your program existed, and a processor that runs nothing but its own instructions. The standard packages usually stand between you and both. This part removes them: you declare and call a system function yourself, use the C runtime directly with its own types and conventions, let C call a Rux function back, and finally write function bodies in assembly for two different processors. Nothing here is everyday code — but after this part you will know what every Io::PrintLine eventually turns into, and how to reach a library no package covers yet.
What you will learn
- Declaring a function from a system library with
extern, and naming the library with#Link. - Why the compiler takes such a declaration on trust, and what happens when it is wrong.
- Calling the C runtime through the
Cpackage: C's own types, opaque pointers, C structs and variadic calls. - Checking C's failure values — null pointers and negative counts — because nothing panics for you.
- Giving a foreign function a Rux name of its own, and choosing a calling convention with
#Abi. - Writing an
asm funcin x86-64 assembly, and its AArch64 version, selected withwhen #target.arch.
The path of a foreign call
From the call site, a foreign function looks like any other. Underneath, each lesson adds one piece of the agreement between the two sides:
flowchart LR
call["A Rux call<br/>GetCurrentProcessId()"] --> decl["extern declaration<br/>name and types,<br/>taken on trust · 24.1"]
decl --> conv["calling convention<br/>which registers carry<br/>the arguments · 24.3"]
conv --> link["#Link<br/>library and symbol<br/>24.1, 24.3"]
link --> lib(["at run time:<br/>the function in Kernel32.dll<br/>or the C runtime · 24.2"])
lib -.->|"a callback, such as<br/>qsort's comparison · 24.3"| back["a Rux function<br/>marked #Abi(.C)"]
asm["A call to an asm func<br/>24.4, 24.5"] --> pin["#Abi: the convention<br/>the body was written for"]
pin --> body(["your instructions,<br/>emitted as written"])| Situation | Tool | Lesson |
|---|---|---|
| a system function no package declares | extern and #Link | Extern |
| anything in the C runtime | the C package | C interop |
| a C name you would rather not spell | #Link's second argument | ABI |
| a Rux function that C calls back | #Abi(.C) | ABI |
| an instruction the language cannot express | asm func | Assembly |
Lessons
| Lesson | What you will learn | |
|---|---|---|
| 24.1 | Extern | call a platform API directly through an extern declaration and #Link |
| 24.2 | C interop | C-compatible types, pointers and handles |
| 24.3 | ABI | choose a calling convention with #Abi |
| 24.4 | Assembly | write a function body in assembly |
| 24.5 | ARM assembly | the same function in AArch64 assembly, chosen with when |
Before you start
Finish Part 23: Compile time first: every lesson here uses when #target to keep platform code out of builds it cannot work in, and #Error to explain why. The C lessons also lean on Part 15: Memory — Pointer, Pointer slice and Layout — and on Defer.
Not every lesson runs everywhere. Extern calls Kernel32.dll and is Windows only; Assembly needs an x86-64 processor; the assembly in ARM assembly runs only on AArch64, though the lesson builds anywhere. C interop and ABI run on Windows, Linux, macOS and FreeBSD. Each lesson's package is in the Examples repository's Platform/ folder:
cd Examples/Platform/Extern
rux run
After this part
That completes the tour of the language and its standard packages. Part 25: Projects puts it all together in complete small programs, and this part's checkpoint, Melody, plays the opening of Ode to Joy through the console speaker by calling the Windows Beep function with extern — so it, too, is Windows only.
For the full rules behind this part, see Foreign function interface, Link, Abi and Assembler functions in the Rux Reference, and the C package in the API reference.