Callbacks
Callbacks allow native libraries to call Haxe code, for example, to invoke a handler when an event happens. Callbacks in C generally belong to two categories:
- Static callbacks — the native library stores a function pointer directly.
- Callbacks with context — the native library stores a function pointer, as well as an additional
void*value which is passed back to the function.
In ammer, a callback is declared using the ammer.ffi.Callback<...> type, which has 5 type parameters:
ammer.ffi.Callback< CallbackType, FunctionType, CallTarget, CallArgs, Lib >
The type parameters should be filled in as follows:
CallbackType— The function type as seen by the native library.FunctionType— The function type as seen by Haxe.CallTarget— An expression (wrapped in square brackets) to reach thevoid*value representing the callback context, or"global".CallArgs— An array of expressions representing the arguments to pass to the Haxe function.Lib— The parentammerlibrary.
It may be convenient to typedef callback types when referring to them within ammer definitions.
Example: declaring and using a callback type
Assuming a C library with the following implementation:
// Type alias for the function type.
// It receives two integer arguments, in addition to the user-defined context.
int32_t (* callback_type)(int32_t, int32_t, void*);
static callback_type *stored_fptr = NULL;
static void *stored_context = NULL;
void store_callback(callback_type *fptr, void *call_context) {
stored_fptr = fptr;
stored_context = call_context;
}
int32_t invoke_callback(int32_t a, int32_t b) {
return stored(a, b, stored_context);
}The callback type can be reflected in ammer as follows:
typedef CallbackType = ammer.ffi.Callback< (ammer.ffi.Int32, ammer.ffi.Int32, Haxe<(Int, Int)->Int>)->ammer.ffi.Int32, (Int, Int)->Int, [arg2], [arg0, arg1], Foobar >;
Note that [arg2] refers to the third, void*-typed argument of callback_type, whereas [arg0, arg1] refer to the first two, int-typed arguments.
The ammer definition for the C library above may look like this:
class Foobar extends ammer.def.Library<"foobar"> { public static function store_callback(_:CallbackType, _:ammer.ffi.Haxe<(Int, Int)->Int>):Void; public static function invoke_callback(_:ammer.ffi.Int32, _:ammer.ffi.Int32):ammer.ffi.Int32; }
Finally, an example of using the library to invoke the callback:
var func = (a:Int, b:Int) -> { return a + b; };
var funcRef = ammer.Lib.createHaxeRef(func);
funcRef.incref();
Foobar.store_callback(funcRef);
// ...
trace(Foobar.invoke_callback(1, 2)); // 3Note the use of createHaxeRef: func is an instance of a Haxe type, thus it must be wrapped with a reference counter as explained in the Haxe types section.