Calling Pawn from Rust — exec_public!¶
Pawn public functions can be called from the plugin. The
exec_public! macro (defined in samp-sdk/src/macros.rs, re-exported
as samp::exec_public) handles the boilerplate: it pushes arguments
in the correct order, allocates AMX
heap memory for owned Rust values, executes the function, and frees
everything when the call returns.
No arguments¶
The macro expands to the equivalent of
amx.find_public("OnMyCallback").and_then(|idx| amx.exec(idx)) and
returns AmxResult<i32> — the Pawn return value (or the propagated
AmxError).
With AmxCell arguments¶
Anything that implements AmxCell is pushed directly. The macro
pushes arguments in reverse order automatically — write them in the
same order as the Pawn signature:
Pawn side:
The same form works for Ref<T>, Buffer, UnsizedBuffer, and any
custom type implementing AmxCell.
With Rust strings — expr => string¶
A Rust &str (or anything that derefs to &str) is copied into the
AMX heap before the call. Use the => string modifier:
The temporary heap allocation is tied to an Allocator created
internally and is reclaimed when the call returns.
With Rust slices — expr => array¶
&[T] where T: AmxCell + AmxPrimitive is copied into a contiguous
AMX buffer:
Mixing argument forms¶
The three forms (expr, expr => string, expr => array) can appear
in any combination:
let public_name = pub_name.to_string();
let owned_msg = String::from("another hello");
let table = vec![10_i32, 20, 30];
exec_public!(
amx,
&public_name,
string, // an existing AmxString argument
"literal" => string, // Rust &str → AMX string
&owned_msg => string, // Rust &String → AMX string
&table => array, // Rust slice → AMX array
reference, // Ref<T> argument
);
The order is the same Pawn sees on the stack — first positional argument first.
Manual equivalent¶
For full control, drop the macro:
let allocator = amx.allocator();
let idx = amx.find_public("OnMessage")?;
let msg = allocator.allot_string("Hello, Pawn!")?;
amx.push(msg)?; // pushed first → last argument in Pawn
amx.push(123_i32)?; // pushed second → first argument in Pawn
let result = amx.exec(idx)?;
allocator releases every AMX heap allocation when it goes out of
scope — there is no need to free memory explicitly.
Return value¶
exec_public! returns AmxResult<i32>:
Ok(value)— the Pawnreturnvalue (cell-encoded; cast withf32::from_bitsif the Pawn function returnsFloat:).Err(AmxError::NotFound)—find_publicdid not locate the function.- Other
AmxErrorvariants are forwarded fromamx_Execdirectly (stack overflow, divide by zero, native failure, …).
See Error handling for the full list.