Commit39253aa3Recorded15 Jul 2026Repositorysigil-ffi
ffi: accept native-codegen closures + route >3-arg callbacks through sigil_applyN
Message
Two callback fixes:
- Native-closure callbacks (latent bug). native_ffi_callback_create rejected any procedure that was not a bytecode closure or native primitive. Under
sigil build --backend native, every top-level procedure is a native-codegen closure (SIGIL_OBJ_NATIVE_CLOSURE), so c-callback rejected EVERY callback in a native-compiled program with 'c-callback: expected procedure', even though the callback handler and the sigil_apply family already dispatch such closures via sigil_native_bridge_call. Now accepts sigil_is_native_closure too.
- Callbacks with more than 3 arguments. The dyncall callback handler erred on any callback with >3 args ('not yet supported'). It now routes the >3-arg case through sigil_applyN (the generic-arity apply added to the VM C-API), supporting up to FFI_MAX_ARGS. This enables 4-6-arg GTK/WebKit signals such as decide-policy.
Proven with a 4-arg WebKitWebView decide-policy callback firing correctly in a native-compiled binary. The >3-arg routing requires sigil_applyN in the linked VM (sigil release that adds it); the native-closure fix is independent.
Changed
native/ffi.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)Diff
native/ffi.cmodified
@@ -27,6 +27,7 @@ extern Value sigil_apply0(SigilVM *vm, Value proc);
27
extern Value sigil_apply1(SigilVM *vm, Value proc, Value arg); 28
extern Value sigil_apply2(SigilVM *vm, Value proc, Value arg1, Value arg2); 29
extern Value sigil_apply3(SigilVM *vm, Value proc, Value arg1, Value arg2, Value arg3);+30
extern Value sigil_applyN(SigilVM *vm, Value proc, int argc, Value *argv); 31
32
/* ============================================================ 33
* FFI Type System@@ -1664,9 +1665,10 @@ static DCsigchar ffi_dyncall_callback_handler(DCCallback *cb, DCArgs *dc_args,
1665
scheme_args[2]); 1666
break; 1667
default:−1667
sigil__vm_error(vm, SIGIL_ERR_RUNTIME,−1668
"c-callback: callbacks with more than 3 arguments not yet supported");−1669
return DC_SIGCHAR_VOID;+1668
/* >3 args: dispatch through the generic arity variant (added to the VM+1669
* C-API alongside sigil_apply0..3). Supports up to FFI_MAX_ARGS. */+1670
ret_val = sigil_applyN(vm, cbd->proc, cbd->arg_count, scheme_args);+1671
break; 1672
} 1673
1674
/* Marshal return value */@@ -1779,9 +1781,15 @@ static Value native_ffi_callback_create(SigilVM *vm, int argc, Value *args)
1781
return SIGIL_UNDEFINED; 1782
} 1783
−1782
/* Procedure */+1784
/* Procedure. Accept bytecode closures, native primitives, AND+1785
* native-codegen closures (SIGIL_OBJ_NATIVE_CLOSURE) - the last is what+1786
* top-level procedures become in --backend native builds, and both the+1787
* callback handler and the sigil_applyN family already dispatch them via+1788
* sigil_native_bridge_call. Without this, c-callback rejects every callback+1789
* in a native-compiled program. */ 1790
Value proc = args[2];−1784
if (!sigil_is_closure(proc) && !sigil_is_native_proc(proc)) {+1791
if (!sigil_is_closure(proc) && !sigil_is_native_proc(proc) &&+1792
!sigil_is_native_closure(proc)) { 1793
sigil__vm_error(vm, SIGIL_ERR_TYPE, 1794
"c-callback: expected procedure"); 1795
return SIGIL_UNDEFINED;