ffi
Call native code. Installed with memory by the ffi capability; nil unless granted. arm64 only.
ffi.call
Section titled “ffi.call”ffi.call(target: pointer|integer, signature: string, ...): any
| Argument | Type | Description |
|---|---|---|
| target | pointer or integer | The callee address. |
| signature | string | "<ret>(<args>)", one char per slot (see below). |
| … | The arguments, one per arg char. |
Calls target. pointer:call(signature, ...) is the same call with the pointer as target.
The signature mini-language
Section titled “The signature mini-language”"<ret>(<args>)", one character per slot:
| Char | Class | Meaning |
|---|---|---|
v |
— | void |
i |
integer | int64 |
u |
integer | uint64 |
p |
integer | pointer / address |
b |
integer | bool |
s |
integer | C string (a Lua string is marshalled to a const char* valid for the call) |
f |
float | float |
d |
float | double |
Returns follow the return char: v gives nil; i/u/p give an integer or pointer (p gives a pointer userdata); f/d give a number; b gives a bool; s reads the returned char* into a Lua string.
Ceiling
Section titled “Ceiling”Enforced: at most 8 integer-class arguments (i u p b s) and 8 float-class arguments (f d). No struct-by-value, no variadic functions. This is the AAPCS64 fixed-prototype limit (x0-x7, d0-d7).
ffi.pointer
Section titled “ffi.pointer”ffi.pointer(n: integer): pointer
Alias of memory.at, familiar from gamesense.
-- call an exported function: int foo(const char*, double)local foo = memory.symbol("libgame.so", "foo")local result = ffi.call(foo, "i(sd)", "hello", 3.5)