dart-sdk/tests/ffi/function_structs_test.dart
Alexander Thomas 2a035279af [3.0 alpha] Use equals for default values in the SDK
The colons cause test failures when the language version is bumped to 3.0. This CL can be landed before the 3.0 version bump.

Bug: https://github.com/dart-lang/language/issues/2357
Change-Id: Id8396034b16adc18b476689314e28b9617d25f18
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/272200
Commit-Queue: Alexander Thomas <athom@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2022-11-30 10:33:31 +00:00

133 lines
3.7 KiB
Dart

// 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.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<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.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);
}