| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| // | |
| // Dart test program for testing dart:ffi function pointers with struct | |
| // arguments. | |
| // | |
| // SharedObjects=ffi_test_functions | |
| import 'dart:ffi'; | |
| import "package:expect/expect.dart"; | |
| import "package:ffi/ffi.dart"; | |
| import 'coordinate.dart'; | |
| import 'dylib_utils.dart'; | |
| import 'very_large_struct.dart'; | |
| typedef NativeCoordinateOp = Pointer<Coordinate> Function(Pointer<Coordinate>); | |
| void main() { | |
| for (final isLeaf in [false, true]) { | |
| testFunctionWithStruct(isLeaf: isLeaf); | |
| testFunctionWithStructArray(isLeaf: isLeaf); | |
| testFunctionWithVeryLargeStruct(isLeaf: isLeaf); | |
| } | |
| } | |
| DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); | |
| /// pass a struct to a c function and get a struct as return value | |
| void testFunctionWithStruct({bool isLeaf = false}) { | |
| Pointer<NativeFunction<NativeCoordinateOp>> p1 = ffiTestFunctions.lookup( | |
| "TransposeCoordinate", | |
| ); | |
| NativeCoordinateOp f1 = (isLeaf | |
| ? p1.asFunction(isLeaf: true) | |
| : p1.asFunction(isLeaf: false)); | |
| ; | |
| final c1 = calloc<Coordinate>() | |
| ..ref.x = 10.0 | |
| ..ref.y = 20.0; | |
| final c2 = calloc<Coordinate>() | |
| ..ref.x = 42.0 | |
| ..ref.y = 84.0 | |
| ..ref.next = c1; | |
| c1.ref.next = c2; | |
| Coordinate result = f1(c1).ref; | |
| Expect.approxEquals(20.0, c1.ref.x); | |
| Expect.approxEquals(30.0, c1.ref.y); | |
| Expect.approxEquals(42.0, result.x); | |
| Expect.approxEquals(84.0, result.y); | |
| calloc.free(c1); | |
| calloc.free(c2); | |
| } | |
| /// pass an array of structs to a c function | |
| void testFunctionWithStructArray({bool isLeaf = false}) { | |
| Pointer<NativeFunction<NativeCoordinateOp>> p1 = ffiTestFunctions.lookup( | |
| "CoordinateElemAt1", | |
| ); | |
| NativeCoordinateOp f1 = (isLeaf | |
| ? p1.asFunction(isLeaf: true) | |
| : p1.asFunction(isLeaf: false)); | |
| ; | |
| final coordinateArray = calloc<Coordinate>(3); | |
| Coordinate c1 = coordinateArray[0]; | |
| Coordinate c2 = coordinateArray[1]; | |
| Coordinate c3 = coordinateArray[2]; | |
| c1.x = 10.0; | |
| c1.y = 10.0; | |
| c1.next = coordinateArray + 2; | |
| c2.x = 20.0; | |
| c2.y = 20.0; | |
| c2.next = coordinateArray + 0; | |
| c3.x = 30.0; | |
| c3.y = 30.0; | |
| c3.next = coordinateArray + 1; | |
| Coordinate result = f1(coordinateArray).ref; | |
| Expect.approxEquals(20.0, result.x); | |
| Expect.approxEquals(20.0, result.y); | |
| calloc.free(coordinateArray); | |
| } | |
| typedef VeryLargeStructSum = int Function(Pointer<VeryLargeStruct>); | |
| typedef NativeVeryLargeStructSum = Int64 Function(Pointer<VeryLargeStruct>); | |
| void testFunctionWithVeryLargeStruct({bool isLeaf = false}) { | |
| Pointer<NativeFunction<NativeVeryLargeStructSum>> p1 = ffiTestFunctions | |
| .lookup("SumVeryLargeStruct"); | |
| VeryLargeStructSum f = (isLeaf | |
| ? p1.asFunction(isLeaf: true) | |
| : p1.asFunction(isLeaf: false)); | |
| ; | |
| final vlsArray = calloc<VeryLargeStruct>(2); | |
| VeryLargeStruct vls1 = vlsArray[0]; | |
| VeryLargeStruct vls2 = vlsArray[1]; | |
| List<VeryLargeStruct> structs = [vls1, vls2]; | |
| for (VeryLargeStruct struct in structs) { | |
| struct.a = 1; | |
| struct.b = 2; | |
| struct.c = 4; | |
| struct.d = 8; | |
| struct.e = 16; | |
| struct.f = 32; | |
| struct.g = 64; | |
| struct.h = 128; | |
| struct.i = 256; | |
| struct.j = 512; | |
| struct.k = 1024; | |
| struct.smallLastField = 1; | |
| } | |
| vls1.parent = vlsArray + 1; | |
| vls1.numChildren = 2; | |
| vls1.children = vlsArray; | |
| vls2.parent = vlsArray + 1; | |
| vls2.parent = nullptr; | |
| vls2.numChildren = 0; | |
| vls2.children = nullptr; | |
| int result = f(vlsArray); | |
| Expect.equals(2051, result); | |
| result = f(vlsArray + 1); | |
| Expect.equals(2048, result); | |
| calloc.free(vlsArray); | |
| } |