#FFI how to pass (or get) 128-bit bigints to (or from) Rust functions?

3 messages · Page 1 of 1 (latest)

eager jolt
#

I want to pass bigints from Deno and get i128 or u128 in Rust. Do I have to use typed arrays for that?

shadow girder
#

Yes. There is currently no "i128" / "u128" option in the FFI parameter / return value types, ie. we do not have a "natively supported" way to pass such arguments.

Additionally, the libffi library Deno uses "under the hood" to implement the C API calls does not support 128 bit integer parameters, so I'm not sure if we even could support these directly. To a degree it's also a question of machine architecture and calling conventions: How are u128 and i128 passed as parameters? Are they passed in two integer registers (on a 64-bit machine)? Or are there special 128-bit registers that are utilized? (Answer seems to be two integer registers, but it may depend on the machine.)

If you control both the JS and Rust side, then I do recommend using a Uint8Array for passing the data: It will be by far fastest that way as this gets to utilize the V8 Fast API path.

ie.

const u128 = BigUint64Array(2);
const u128Param = new Uint8Array(u128.buffer); // Not a copy, but a reference
u128[0] = BigInt(235234568686);
u128[1] = BigInt(2363447347)
lib.symbols.call(u128Param);

and on Rust side:

extern "C" fn call(u128Param: *mut u128) {
  printf("Got u128 from JavaScript: {}", unsafe { *u128Param });
}
mighty spindle