diff options
author | Dj <43033058+DjDeveloperr@users.noreply.github.com> | 2023-01-07 19:58:10 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-08 09:28:10 +0530 |
commit | ad82918f56b215a428ebe7c533ee825e1152d1b4 (patch) | |
tree | 2669f9d8d419a88e9d58b12b98579e884aec6988 /test_ffi/tests | |
parent | 84ef26ac9b5f0e1199d77837cd97cb203baa8729 (diff) |
feat(ext/ffi): structs by value (#15060)
Adds support for passing and returning structs as buffers to FFI. This does not implement fastapi support for structs. Needed for certain system APIs such as AppKit on macOS.
Diffstat (limited to 'test_ffi/tests')
-rw-r--r-- | test_ffi/tests/ffi_types.ts | 9 | ||||
-rw-r--r-- | test_ffi/tests/integration_tests.rs | 4 | ||||
-rw-r--r-- | test_ffi/tests/test.js | 76 |
3 files changed, 80 insertions, 9 deletions
diff --git a/test_ffi/tests/ffi_types.ts b/test_ffi/tests/ffi_types.ts index 058138a8d..d7c66203c 100644 --- a/test_ffi/tests/ffi_types.ts +++ b/test_ffi/tests/ffi_types.ts @@ -66,17 +66,10 @@ const remote = Deno.dlopen( Deno.dlopen( "dummy_lib_2.so", - // is declared using "pointer" or "function" + UnsafeFnPointer { wrong_method1: { parameters: [], - // @ts-expect-error not assignable to type 'NativeResultType' - result: { - function: { - parameters: [], - result: "void", - }, - }, + result: "function", }, }, ); diff --git a/test_ffi/tests/integration_tests.rs b/test_ffi/tests/integration_tests.rs index 6564f1e14..3c86d6d4d 100644 --- a/test_ffi/tests/integration_tests.rs +++ b/test_ffi/tests/integration_tests.rs @@ -127,6 +127,10 @@ fn basic() { Static i64: -1242464576485\n\ Static ptr: true\n\ Static ptr value: 42\n\ + Rect { x: 10.0, y: 20.0, w: 100.0, h: 200.0 }\n\ + Rect { x: 10.0, y: 20.0, w: 100.0, h: 200.0 }\n\ + Rect { x: 20.0, y: 20.0, w: 100.0, h: 200.0 }\n\ + Mixed { u8: 3, f32: 12.515, rect: Rect { x: 10.0, y: 20.0, w: 100.0, h: 200.0 }, usize: 12456789, array: [8, 32] }\n\ arrayBuffer.byteLength: 4\n\ uint32Array.length: 1\n\ uint32Array[0]: 42\n\ diff --git a/test_ffi/tests/test.js b/test_ffi/tests/test.js index 3bbf475e9..0ada7dc0a 100644 --- a/test_ffi/tests/test.js +++ b/test_ffi/tests/test.js @@ -3,7 +3,7 @@ // Run using cargo test or `--v8-options=--allow-natives-syntax` -import { assertEquals, assertNotEquals } from "https://deno.land/std@0.149.0/testing/asserts.ts"; +import { assertEquals, assertInstanceOf, assertNotEquals } from "https://deno.land/std@0.149.0/testing/asserts.ts"; import { assertThrows, assert, @@ -37,6 +37,12 @@ assertThrows( "Failed to register symbol non_existent_symbol", ); +const Point = ["f64", "f64"]; +const Size = ["f64", "f64"]; +const Rect = ["f64", "f64", "f64", "f64"]; +const RectNested = [{ struct: Point }, { struct: Size }]; +const Mixed = ["u8", "f32", { struct: Rect }, "usize", { struct: ["u32", "u32"] }]; + const dylib = Deno.dlopen(libPath, { "printSomething": { name: "print_something", @@ -210,6 +216,34 @@ const dylib = Deno.dlopen(libPath, { type: "pointer", }, "hash": { parameters: ["buffer", "u32"], result: "u32" }, + make_rect: { + parameters: ["f64", "f64", "f64", "f64"], + result: { struct: Rect }, + }, + make_rect_async: { + name: "make_rect", + nonblocking: true, + parameters: ["f64", "f64", "f64", "f64"], + result: { struct: RectNested }, + }, + print_rect: { + parameters: [{ struct: Rect }], + result: "void", + }, + print_rect_async: { + name: "print_rect", + nonblocking: true, + parameters: [{ struct: Rect }], + result: "void", + }, + create_mixed: { + parameters: ["u8", "f32", { struct: Rect }, "pointer", "buffer"], + result: { struct: Mixed } + }, + print_mixed: { + parameters: [{ struct: Mixed }], + result: "void", + }, }); const { symbols } = dylib; @@ -571,6 +605,46 @@ console.log( const view = new Deno.UnsafePointerView(dylib.symbols.static_ptr); console.log("Static ptr value:", view.getUint32()); +// Test struct returning +const rect_sync = dylib.symbols.make_rect(10, 20, 100, 200); +assertInstanceOf(rect_sync, Uint8Array); +assertEquals(rect_sync.length, 4 * 8); +assertEquals(Array.from(new Float64Array(rect_sync.buffer)), [10, 20, 100, 200]); +// Test struct passing +dylib.symbols.print_rect(rect_sync); +// Test struct passing asynchronously +await dylib.symbols.print_rect_async(rect_sync); +dylib.symbols.print_rect(new Float64Array([20, 20, 100, 200])); +// Test struct returning asynchronously +const rect_async = await dylib.symbols.make_rect_async(10, 20, 100, 200); +assertInstanceOf(rect_async, Uint8Array); +assertEquals(rect_async.length, 4 * 8); +assertEquals(Array.from(new Float64Array(rect_async.buffer)), [10, 20, 100, 200]); + +// Test complex, mixed struct returning and passing +const mixedStruct = dylib.symbols.create_mixed(3, 12.515000343322754, rect_async, 12456789, new Uint32Array([8, 32])); +assertEquals(mixedStruct.length, 56); +assertEquals(Array.from(mixedStruct.subarray(0, 4)), [3, 0, 0, 0]); +assertEquals(new Float32Array(mixedStruct.buffer, 4, 1)[0], 12.515000343322754); +assertEquals(new Float64Array(mixedStruct.buffer, 8, 4), new Float64Array(rect_async.buffer)); +assertEquals(new BigUint64Array(mixedStruct.buffer, 40, 1)[0], 12456789n); +assertEquals(new Uint32Array(mixedStruct.buffer, 48, 2), new Uint32Array([8, 32])); +dylib.symbols.print_mixed(mixedStruct); + +const cb = new Deno.UnsafeCallback({ + parameters: [{ struct: Rect }], + result: { struct: Rect }, +}, (innerRect) => { + innerRect = new Float64Array(innerRect.buffer); + return new Float64Array([innerRect[0] + 10, innerRect[1] + 10, innerRect[2] + 10, innerRect[3] + 10]); +}); + +const cbFfi = new Deno.UnsafeFnPointer(cb.pointer, cb.definition); +const cbResult = new Float64Array(cbFfi.call(rect_async).buffer); +assertEquals(Array.from(cbResult), [20, 30, 110, 210]); + +cb.close(); + const arrayBuffer = view.getArrayBuffer(4); const uint32Array = new Uint32Array(arrayBuffer); console.log("arrayBuffer.byteLength:", arrayBuffer.byteLength); |