mirror of
https://github.com/fluffos/fluffos
synced 2026-08-12 18:26:06 -04:00
Fully implements the docs/driver/ffi-plan.md design. LPC can now load native shared libraries, call C functions whose signatures are described at runtime, manage native memory, pass in/out parameters, and expose LPC function pointers to C as callbacks. Package (src/packages/ffi, option PACKAGE_FFI ON, libffi via pkg-config): - ffi_load/unload/symbol; ffi_prepare/ffi_call (ffi_prep_cif + ffi_call); ffi_alloc/free/sizeof/peek/address; ffi_read/write; ffi_struct_layout; ffi_callback/ffi_callback_addr/ffi_callback_free (libffi closures that re-enter the VM via safe_call_function_pointer); ffi_error/ffi_status. - Buffers are the currency for all pointer/byte data; raw pointer VALUES (returned pointers, buffer/callback addresses) are ints. LPC strings are UTF-8-native and never implicitly marshalled -- a char* is a buffer the caller encoded (pinned by ffi_string.lpc). - Native allocations are LPC buffers (GC-tracked); handle tables freed at shutdown (ffi_cleanup) and marked for DEBUGMALLOC (mark_ffi). Security: master apply valid_ffi(op, arg, caller) gates every load/symbol/prepare/callback (VALID_FFI added to the applies table); a missing apply denies by default. Optional "ffi allowed libraries" config allow-list (rc.cc + runtime_config.h + regenerated config.md, new Security category). __PACKAGE_FFI__ predefine added. tools/ffi/generate.py: turns a C header into LPC bindings (buffer params for char*, optional --string-convenience UTF-8 overloads) plus a struct layout include; reports+skips unsupported forms; --emit-json contract. Dependency-free test.py. Tests: 20 testsuite/single/tests/efuns/ffi_*.lpc (every efun, the qsort callback round trip, the generated-bindings end-to-end path), guarded by __PACKAGE_FFI__ with a libc-reachability probe. The efuns are VM-stack- based, so the LPC testsuite is the surface -- libffi's call/closure paths run there under ASan/UBSan and the per-file check_memory leak gate. The clang RelWithDebInfo sanitizer caught an error()-unwind leak: both ffi_prepare and ffi_callback allocated before a code_to_type() that can error() -- now unique_ptr/custom-deleter owned (AGENTS.md section 4). Verified: testsuite x3 (ASan Debug) + ctest 297, RelWithDebInfo suite x3 + ctest 298, clang RelWithDebInfo sanitizer (leak-clean), tools/ffi test.py. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
25 lines
666 B
C
25 lines
666 B
C
/* Sample header for tools/ffi/test.py -- exercises the generator's C
|
|
* subset: scalar/pointer/string params, void return, structs, and the
|
|
* unsupported forms it must skip. */
|
|
|
|
extern double sqrt(double x);
|
|
extern double pow(double base, double exp);
|
|
int abs(int n);
|
|
size_t strlen(const char *s);
|
|
void qsort(void *base, size_t nmemb, size_t size, void *compar);
|
|
|
|
/* Unsupported: variadic and a raw function-pointer parameter -- both
|
|
* must be reported and skipped, never mis-bound. */
|
|
int printf(const char *fmt, ...);
|
|
void set_handler(int (*cb)(int));
|
|
|
|
struct Point {
|
|
int x;
|
|
int y;
|
|
};
|
|
|
|
struct Mixed {
|
|
char tag;
|
|
double value;
|
|
short flags;
|
|
};
|