Rename all example tests/companions to the XXXX-category-test-name scheme (per-category 100-blocks: basic 0010, types 0100, ... errors 1000, diagnostics 1100, ffi 1200, ffi-objc 1300, ffi-jni 1400, vectors 1500, platform 1600). Companions and dir/C fixtures move in lockstep with their parent test; #import/#source/#include paths rewritten to match. Expected output now lives in examples/expected/ (a sibling dir of the tests) split into three streams per the new convention: <name>.exit / <name>.stdout / <name>.stderr (+ optional <name>.ir) run_examples.sh rewritten: scans examples/ and issues/ for an expected/<name>.exit marker, captures stdout and stderr separately (no more 2>&1), compares each stream + exit + optional IR snapshot. Behavior validated unchanged: every renamed test reproduces its prior merged output + exit (diffs limited to file paths/basenames embedded in diagnostics + traces, which correctly reflect the new names). Suite: 292 passed, 0 failed. 50-smoke.sx split + issue relocation + docs follow in subsequent commits.
60 lines
2.2 KiB
Plaintext
60 lines
2.2 KiB
Plaintext
// Phase 0 baseline (PLAN-FFI.md step 0.6): sx function passed to C
|
|
// as a function pointer; C invokes it; sx-side observable effect.
|
|
// Mirrors the `app->onInputEvent` install pattern in
|
|
// library/modules/platform/android.sx.
|
|
//
|
|
// Two arities covered:
|
|
// 1. (s32) -> s32 — single-arg callback
|
|
// 2. (*void, s32) -> s32 — pointer + value (onInputEvent shape)
|
|
//
|
|
// Plus a side-effect via a global so we can confirm the callback
|
|
// actually fired (return value + state mutation both observable).
|
|
|
|
#import "modules/std.sx";
|
|
|
|
#import c {
|
|
#source "1214-ffi-06-callback.c";
|
|
};
|
|
|
|
ffi_apply_callback :: (cb: (s32) -> s32 callconv(.c), value: s32) -> s32 #foreign;
|
|
ffi_apply_callback2 :: (cb: (*void, s32) -> s32 callconv(.c), ctx: *void, v: s32) -> s32 #foreign;
|
|
|
|
g_callback_hits : s32 = 0;
|
|
g_callback_sum : s32 = 0;
|
|
|
|
double_it :: (x: s32) -> s32 callconv(.c) {
|
|
g_callback_hits += 1;
|
|
g_callback_sum += x;
|
|
x * 2;
|
|
}
|
|
|
|
add_with_ctx :: (ctx: *void, v: s32) -> s32 callconv(.c) {
|
|
g_callback_hits += 1;
|
|
// Pass a sentinel via ctx to prove the pointer arg also survives the
|
|
// round-trip — read it back as an s32 through *s32.
|
|
p : *s32 = xx ctx;
|
|
p.* + v;
|
|
}
|
|
|
|
main :: () -> s32 {
|
|
// ── Single-arg callback ────────────────────────────────────────
|
|
r1 := ffi_apply_callback(double_it, 21);
|
|
print("callback returned = {}\n", r1);
|
|
print("hits after first call = {}\n", g_callback_hits);
|
|
print("sum after first call = {}\n", g_callback_sum);
|
|
|
|
// Two more calls confirm the same fn pointer keeps working.
|
|
ffi_apply_callback(double_it, 7);
|
|
ffi_apply_callback(double_it, 11);
|
|
print("hits after three calls = {}\n", g_callback_hits);
|
|
print("sum after three calls = {}\n", g_callback_sum);
|
|
|
|
// ── Two-arg callback with opaque ctx pointer ───────────────────
|
|
ctx_val : s32 = 100;
|
|
r2 := ffi_apply_callback2(add_with_ctx, xx @ctx_val, 42);
|
|
print("ctx + value = {}\n", r2);
|
|
print("hits after ctx callback = {}\n", g_callback_hits);
|
|
|
|
0;
|
|
}
|