# Function pointers

Function pointers exist; closures do not. There is no captured environment to reason about.

## Type position

```cplus
fn(i32, i32) -> i32          // takes two i32, returns i32
fn(*u8)                       // takes *u8, returns unit
```

## Coercion

A bare function identifier coerces to a function pointer in a position that expects one:

```cplus
extern fn atexit(cb: fn()) -> i32;
fn cleanup() { println(99); }

fn main() -> i32 {
    unsafe { atexit(cleanup); }    // bare name coerces
    return 0;
}
```

## A struct of callbacks

```cplus
struct Actions {
    on_click: fn(i32) -> i32,
    on_hover: fn(i32) -> i32,
}

let a: Actions = Actions { on_click: handle_click, on_hover: handle_hover };
let r: i32 = a.on_click(7);     // indirect call through the field
```

## Stateful callbacks: the C convention

Function pointers do not capture environment, so for a callback that needs state, do what C does: pass `(fn_ptr, user_data: *u8)` and have the library thread `user_data` back to you unchanged.

```cplus
extern fn libfoo_subscribe(cb: fn(*u8, i32), user_data: *u8);
```

This is also how [appkit](/docs/packages/appkit) wires UI callbacks: a named function plus an associated object, never a closure.
