# ffi

Call native code. Installed with [`memory`](/base/memory/) by the `ffi` capability; `nil` unless granted. arm64 only.

#### 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

`"<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

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

`ffi.pointer(n: integer)`: pointer

Alias of `memory.at`, familiar from gamesense.

```lua
-- 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)
```