// 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 Function(Pointer); 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> p1 = ffiTestFunctions.lookup("TransposeCoordinate"); NativeCoordinateOp f1 = (isLeaf ? p1.asFunction(isLeaf: true) : p1.asFunction(isLeaf: false)); ; final c1 = calloc() ..ref.x = 10.0 ..ref.y = 20.0; final c2 = calloc() ..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> p1 = ffiTestFunctions.lookup("CoordinateElemAt1"); NativeCoordinateOp f1 = (isLeaf ? p1.asFunction(isLeaf: true) : p1.asFunction(isLeaf: false)); ; final coordinateArray = calloc(3); Coordinate c1 = coordinateArray[0]; Coordinate c2 = coordinateArray[1]; Coordinate c3 = coordinateArray[2]; c1.x = 10.0; c1.y = 10.0; c1.next = coordinateArray.elementAt(2); c2.x = 20.0; c2.y = 20.0; c2.next = coordinateArray.elementAt(0); c3.x = 30.0; c3.y = 30.0; c3.next = coordinateArray.elementAt(1); Coordinate result = f1(coordinateArray.elementAt(0)).ref; Expect.approxEquals(20.0, result.x); Expect.approxEquals(20.0, result.y); calloc.free(coordinateArray); } typedef VeryLargeStructSum = int Function(Pointer); typedef NativeVeryLargeStructSum = Int64 Function(Pointer); void testFunctionWithVeryLargeStruct({bool isLeaf: false}) { Pointer> p1 = ffiTestFunctions.lookup("SumVeryLargeStruct"); VeryLargeStructSum f = (isLeaf ? p1.asFunction(isLeaf: true) : p1.asFunction(isLeaf: false)); ; final vlsArray = calloc(2); VeryLargeStruct vls1 = vlsArray[0]; VeryLargeStruct vls2 = vlsArray[1]; List 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.elementAt(1); vls1.numChildren = 2; vls1.children = vlsArray.elementAt(0); vls2.parent = vlsArray.elementAt(1); vls2.parent = nullptr; vls2.numChildren = 0; vls2.children = nullptr; int result = f(vlsArray.elementAt(0)); Expect.equals(2051, result); result = f(vlsArray.elementAt(1)); Expect.equals(2048, result); calloc.free(vlsArray); }