char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somffi: add avril-ffi crate and avril:ffi moduled401c8e

main
2.1 KiB49 linesraw

avril:ffi

avril:ffi loads shared libraries and calls their symbols in-process:

import { dlopen } from "avril:ffi";

const lib = dlopen("./libadd.so", {
  add: { parameters: ["i32", "i32"], result: "i32" },
});
console.log(lib.symbols.add(40, 2)); // 42
lib.close();

Native code is not sandboxed: it runs with the process's full authority and a native crash takes the runtime with it. Loading a library therefore requires the ffi capability:

  • avril run --allow-ffi=./libadd.so main.js, or --deny-ffi= to revoke. Path grants name one library entry, like run grants: aliases and hard links need their own entries.
  • A bare name (dlopen("libsqlite3.so")) is resolved by the system loader and requires unrestricted ffi authority.
  • pledge({ ffi: false }) (or an allow/deny restriction) narrows it at runtime; -0 starts with none.

types

void, bool, i8–i64, u8–u64, isize, usize, f32, f64, pointer, buffer (parameters only), and function (parameters and results). 64-bit integers, isize/usize, and pointers cross the boundary as bigint. Out-of-range integer arguments throw instead of wrapping.

A definition may set name when the symbol differs from its key, and nonblocking: true to run the call on a native thread and return a Promise; buffer arguments are copied in for nonblocking calls, and the bytes the native call changed are written back on completion, while raw pointers must name memory that outlives the call.

UnsafePointer creates and offsets opaque Pointers, UnsafePointerView reads and writes through them (including C strings), and UnsafeFnPointer calls function pointers such as those returned from native code. A Pointer taken from a view does not keep the view alive. Pointer and function-pointer values obtained from a library dangle once that library is closed; using them afterwards is undefined behavior. Pointer operations require holding some ffi authority, as dlopen does.

Not yet supported: UnsafeCallback (JS functions callable from native code), struct-by-value arguments, and variadic functions.

1# avril:ffi
2
3`avril:ffi` loads shared libraries and calls their symbols in-process:
4
5```js
6import { dlopen } from "avril:ffi";
7
8const lib = dlopen("./libadd.so", {
9  add: { parameters: ["i32", "i32"], result: "i32" },
10});
11console.log(lib.symbols.add(40, 2)); // 42
12lib.close();
13```
14
15Native code is not sandboxed: it runs with the process's full authority and
16a native crash takes the runtime with it. Loading a library therefore
17requires the `ffi` capability:
18
19- `avril run --allow-ffi=./libadd.so main.js`, or `--deny-ffi=` to revoke.
20  Path grants name one library entry, like `run` grants: aliases and hard
21  links need their own entries.
22- A bare name (`dlopen("libsqlite3.so")`) is resolved by the system loader
23  and requires unrestricted `ffi` authority.
24- `pledge({ ffi: false })` (or an allow/deny restriction) narrows it at
25  runtime; `-0` starts with none.
26
27## types
28
29`void`, `bool`, `i8`–`i64`, `u8`–`u64`, `isize`, `usize`, `f32`, `f64`,
30`pointer`, `buffer` (parameters only), and `function` (parameters and
31results). 64-bit integers, `isize`/`usize`, and pointers cross the boundary
32as `bigint`. Out-of-range integer arguments throw instead of wrapping.
33
34A definition may set `name` when the symbol differs from its key, and
35`nonblocking: true` to run the call on a native thread and return a
36`Promise`; `buffer` arguments are copied in for nonblocking calls, and the
37bytes the native call changed are written back on completion, while raw
38pointers must name memory that outlives the call.
39
40`UnsafePointer` creates and offsets opaque `Pointer`s, `UnsafePointerView`
41reads and writes through them (including C strings), and `UnsafeFnPointer`
42calls function pointers such as those returned from native code. A
43`Pointer` taken from a view does not keep the view alive. Pointer and
44function-pointer values obtained from a library dangle once that library is
45closed; using them afterwards is undefined behavior. Pointer operations
46require holding some `ffi` authority, as `dlopen` does.
47
48Not yet supported: `UnsafeCallback` (JS functions callable from native
49code), struct-by-value arguments, and variadic functions.