4 ms·
One of the features missing in bun:ffi is inferring types for symbols from header files. This would let you import C libraries in JavaScript/TypeScript directly
by Jarred 2y ago
One of the features missing in bun:ffi is inferring types for symbols from header files. This would let you import C libraries in JavaScript/TypeScript directly, without having to configure bindings.
We embed TinyCC for FFI, but TinyCC doesn't expose a way to read the types for exported symbols.
Currently, it looks like this:
import { dlopen, FFIType, suffix } from "bun:ffi";
// `suffix` is either "dylib", "so", or "dll" depending on the platform
// you don't have to use "suffix", it's just there for convenience
const path = `libsqlite3.${suffix}`;
const {
symbols: {
sqlite3_libversion, // the function to call
},
} = dlopen(
path, // a library name or file path
{
sqlite3_libversion: {
// no arguments, returns a string
args: [],
returns: FFIType.cstring,
},
},
);
console.log(`SQLite 3 version: ${sqlite3_libversion()}`);
It would be nicer if it was something like this:
import {sqlite3_libversion as version} from "sqlite3.h" with {lib: "sqlite3"};
console.log(`SQLite 3 version: ${version()}`);
Would love to use Aro to do this in the future
- grahamjameson 2y agoPerhaps a middle-of-the-road approach would be to use inline C like LuaJIT's FFI does? For instance: new_clib("/system/lib64/liblog.so", "log") ffi.cdef[[int __android_log_print(int priority, const char *tag, const char *msg);]] ffi.log.__android_log_print(5, "TEST_TAG", "Hello from FFI") I can't say I'm familiar with Bun, but I've used a similar syntax to the example you provided of the current Bun syntax when working with Frida (https://frida.re https://frida.re). I agree it leaves something to be desired and indeed it would be cool if Aro could do this in the future.
- mananaysiempre 2y agoLuaJIT spends about 2000 lines[1] on its C parser which even includes a limited expression evaluator, though not a preprocessor. My experience suggests explicit memory management could add half again that (LuaJIT’s piggybacks on its GC), and writing one is something like a month of work even if you know exactly what you’re doing (I didn’t), but in any case it’s not a monumental task. [1] https://repo.or.cz/luajit-2.0.git/blob/HEAD:/src/lj_cparse.c https://repo.or.cz/luajit-2.0.git/blob/HEAD:/src/lj_cparse.c
- grahamjameson 2y ago[dead]
- WalterBright 2y agoWith D it is: import sqlite3; This causes sqlite3.h to be read, lexed, parsed, and semantically analyzed to convert (where possible) C symbols to D symbols, and makes them available to the importer. I've been sometimes pressured to instead use various more complicated syntaxes, but have held the line :-)
- WhereIsTheTruth 2y agoWhat i like to use is to isolate the imports from C, since they usually come with other definitions wich might clash (already defined error thingy): import c = sqlite3; On that topic, i wish it was possible to group named imports, perhaps this way: import c = sqlite3, miniz;