From aa36c1fbc5a52b6fecca4aa55a1b1ec56f34e6b4 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Wed, 23 Oct 2019 22:20:37 +0000 Subject: [PATCH] [samples/ffi] Fix samples and run them as test Change-Id: I49eeba32d99c9cf916d25150b46fa6d74ece0092 Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-dartkb-linux-debug-simarm64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-dartkb-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-precomp-mac-release-simarm_x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122382 Commit-Queue: Daco Harkes Reviewed-by: Martin Kustermann --- samples/ffi/coordinate.dart | 20 +-- samples/ffi/dylib_utils.dart | 9 +- samples/ffi/sample_ffi_data.dart | 87 ++++------- samples/ffi/sample_ffi_dynamic_library.dart | 8 +- samples/ffi/sample_ffi_functions.dart | 146 ++++++++---------- .../ffi/sample_ffi_functions_callbacks.dart | 55 ++++--- samples/ffi/sample_ffi_functions_structs.dart | 53 +++---- samples/ffi/sample_ffi_structs.dart | 42 ++--- samples/ffi/samples_test.dart | 23 +++ samples/ffi/sqlite/docs/android.md | 2 +- .../ffi/sqlite/lib/src/ffi/dylib_utils.dart | 6 +- samples/ffi/sqlite/test/sqlite_test.dart | 13 +- samples/samples.status | 5 +- 13 files changed, 221 insertions(+), 248 deletions(-) create mode 100644 samples/ffi/samples_test.dart diff --git a/samples/ffi/coordinate.dart b/samples/ffi/coordinate.dart index 2246f032fb3..c5d96a23989 100644 --- a/samples/ffi/coordinate.dart +++ b/samples/ffi/coordinate.dart @@ -2,11 +2,9 @@ // 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. -library FfiTest; - import 'dart:ffi'; -import 'package:ffi/ffi.dart' as ffi; +import "package:ffi/ffi.dart"; /// Sample struct for dart:ffi library. class Coordinate extends Struct { @@ -18,20 +16,10 @@ class Coordinate extends Struct { Pointer next; - // Implementation generated by @ffi.struct annotation. - external static int sizeOf(); - - Coordinate elementAt(int index) => addressOf.elementAt(index).ref; - - static Coordinate allocate({int count: 1}) => - ffi.allocate(count: count).ref; - - /// Allocate a new [Coordinate] in C memory and populate its fields. - factory Coordinate(double x, double y, Coordinate next) { - Coordinate result = Coordinate.allocate() + factory Coordinate.allocate(double x, double y, Pointer next) { + return allocate().ref ..x = x ..y = y - ..next = next.addressOf; - return result; + ..next = next; } } diff --git a/samples/ffi/dylib_utils.dart b/samples/ffi/dylib_utils.dart index 1c924d4a838..7304a7e4dc6 100644 --- a/samples/ffi/dylib_utils.dart +++ b/samples/ffi/dylib_utils.dart @@ -2,18 +2,19 @@ // 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. -import 'dart:ffi' as ffi; +import 'dart:ffi'; import 'dart:io' show Platform; String _platformPath(String name, {String path}) { if (path == null) path = ""; - if (Platform.isLinux) return path + "lib" + name + ".so"; + if (Platform.isLinux || Platform.isAndroid) + return path + "lib" + name + ".so"; if (Platform.isMacOS) return path + "lib" + name + ".dylib"; if (Platform.isWindows) return path + name + ".dll"; throw Exception("Platform not implemented"); } -ffi.DynamicLibrary dlopenPlatformSpecific(String name, {String path}) { +DynamicLibrary dlopenPlatformSpecific(String name, {String path}) { String fullPath = _platformPath(name, path: path); - return ffi.DynamicLibrary.open(fullPath); + return DynamicLibrary.open(fullPath); } diff --git a/samples/ffi/sample_ffi_data.dart b/samples/ffi/sample_ffi_data.dart index 7b349177394..8e713d03ff2 100644 --- a/samples/ffi/sample_ffi_data.dart +++ b/samples/ffi/sample_ffi_data.dart @@ -5,11 +5,11 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; -main(List arguments) { +main() { print('start main'); { - // basic operation: allocate, get, set, and free + // Basic operation: allocate, get, set, and free. Pointer p = allocate(); p.value = 42; int pValue = p.value; @@ -18,7 +18,7 @@ main(List arguments) { } { - // undefined behavior before set + // Undefined behavior before set. Pointer p = allocate(); int pValue = p.value; print('If not set, returns garbage: ${pValue}'); @@ -26,7 +26,7 @@ main(List arguments) { } { - // pointers can be created from an address + // Pointers can be created from an address. Pointer pHelper = allocate(); pHelper.value = 1337; @@ -40,31 +40,31 @@ main(List arguments) { } { - // address is zeroed out after free + // Address is zeroed out after free. Pointer p = allocate(); free(p); print('After free, address is zero: ${p.address}'); } { - // allocating too much throws an exception + // Allocating too much throws an exception. try { int maxMint = 9223372036854775807; // 2^63 - 1 allocate(count: maxMint); - } on RangeError { + } on Error { print('Expected exception on allocating too much'); } try { int maxInt1_8 = 1152921504606846975; // 2^60 -1 allocate(count: maxInt1_8); - } on ArgumentError { + } on Error { print('Expected exception on allocating too much'); } } { - // pointers can be cast into another type - // resulting in the corresponding bits read + // Pointers can be cast into another type, + // resulting in the corresponding bits read. Pointer p1 = allocate(); p1.value = 9223372036854775807; // 2^63 - 1 @@ -78,7 +78,7 @@ main(List arguments) { } { - // data can be tightly packed in memory + // Data can be tightly packed in memory. Pointer p = allocate(count: 8); for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) { p.elementAt(i).value = i * 3; @@ -90,20 +90,18 @@ main(List arguments) { } { - // exception on storing a value that does not fit + // Values that don't fit are truncated. Pointer p11 = allocate(); - try { - p11.value = 9223372036854775807; - } on ArgumentError { - print('Expected exception on calling set with a value that does not fit'); - } + p11.value = 9223372036854775807; + + print(p11); free(p11); } { - // doubles + // Doubles. Pointer p = allocate(); p.value = 3.14159265359; print('${p.runtimeType} value: ${p.value}'); @@ -113,7 +111,7 @@ main(List arguments) { } { - // floats + // Floats. Pointer p = allocate(); p.value = 3.14159265359; print('${p.runtimeType} value: ${p.value}'); @@ -123,8 +121,8 @@ main(List arguments) { } { - // IntPtr varies in size based on whether the platform is 32 or 64 bit - // addresses of pointers fit in this size + // IntPtr varies in size based on whether the platform is 32 or 64 bit. + // Addresses of pointers fit in this size. Pointer p = allocate(); int p14addr = p.address; p.value = p14addr; @@ -134,36 +132,28 @@ main(List arguments) { } { - // void pointers are unsized - // the size of the element it is pointing to is undefined - // this means they cannot be allocated, read, or written - // this would would fail to compile: - // allocate(); + // Void pointers are unsized. + // The size of the element it is pointing to is undefined, + // they cannot be allocated, read, or written. Pointer p1 = allocate(); Pointer p2 = p1.cast(); print('${p2.runtimeType} address: ${p2.address}'); - // this fails to compile, we cannot read something unsized - // p2.load(); - - // this fails to compile, we cannot write something unsized - // p2.store(1234); - free(p1); } { - // pointer to a pointer to something + // Pointer to a pointer to something. Pointer pHelper = allocate(); pHelper.value = 17; Pointer> p = allocate(); - // storing into a pointer pointer automatically unboxes + // Storing into a pointer pointer automatically unboxes. p.value = pHelper; - // reading from a pointer pointer automatically boxes + // Reading from a pointer pointer automatically boxes. Pointer pHelper2 = p.value; print('${pHelper2.runtimeType} value: ${pHelper2.value}'); @@ -175,23 +165,22 @@ main(List arguments) { } { - // the pointer to pointer types must match up + // The pointer to pointer types must match up. Pointer pHelper = allocate(); pHelper.value = 123; Pointer> p = allocate(); - // this fails to compile due to type mismatch - // p.store(pHelper); + // Trying to store `pHelper` into `p.val` would result in a type mismatch. free(pHelper); free(p); } { - // null pointer in Dart points to address 0 in c++ + // `nullptr` points to address 0 in c++. Pointer> pointerToPointer = allocate(); - Pointer value = null; + Pointer value = nullptr; pointerToPointer.value = value; value = pointerToPointer.value; print("Loading a pointer to the 0 address is null: ${value}"); @@ -199,27 +188,17 @@ main(List arguments) { } { - // sizeof returns element size in bytes + // The toplevel function sizeOf returns element size in bytes. print('sizeOf(): ${sizeOf()}'); print('sizeOf(): ${sizeOf()}'); print('sizeOf(): ${sizeOf()}'); } { - // only concrete sub types of NativeType can be allocated - // this would fail to compile: - // allocate(); - } - - { - // only concrete sub types of NativeType can be asked for size - // this would fail to compile: - // sizeOf(); - } - - { - // with IntPtr pointers, one can manually setup aribtrary data + // With IntPtr pointers, one could manually setup aribtrary data // structres in C memory. + // + // However, it is advised to use Pointer> for that. void createChain(Pointer head, int length, int value) { if (length == 0) { diff --git a/samples/ffi/sample_ffi_dynamic_library.dart b/samples/ffi/sample_ffi_dynamic_library.dart index 234e3d020ab..28772ff4601 100644 --- a/samples/ffi/sample_ffi_dynamic_library.dart +++ b/samples/ffi/sample_ffi_dynamic_library.dart @@ -2,16 +2,16 @@ // 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. -import 'dart:ffi' as ffi; +import 'dart:ffi'; import 'dylib_utils.dart'; -typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double); +typedef NativeDoubleUnOp = Double Function(Double); typedef DoubleUnOp = double Function(double); -main(List arguments) { - ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); +main() { + DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); print(l); print(l.runtimeType); diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart index 4275b3d4d59..72db3ebdf34 100644 --- a/samples/ffi/sample_ffi_functions.dart +++ b/samples/ffi/sample_ffi_functions.dart @@ -2,69 +2,48 @@ // 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. -import 'dart:ffi' as ffi; +import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'dylib_utils.dart'; -typedef NativeUnaryOp = ffi.Int32 Function(ffi.Int32); -typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32); +typedef NativeUnaryOp = Int32 Function(Int32); +typedef NativeBinaryOp = Int32 Function(Int32, Int32); typedef UnaryOp = int Function(int); typedef BinaryOp = int Function(int, int); typedef GenericBinaryOp = int Function(int, T); -typedef NativeQuadOpSigned = ffi.Int64 Function( - ffi.Int64, ffi.Int32, ffi.Int16, ffi.Int8); -typedef NativeQuadOpUnsigned = ffi.Uint64 Function( - ffi.Uint64, ffi.Uint32, ffi.Uint16, ffi.Uint8); -typedef NativeFunc4 = ffi.IntPtr Function(ffi.IntPtr); -typedef NativeDoubleUnaryOp = ffi.Double Function(ffi.Double); -typedef NativeFloatUnaryOp = ffi.Float Function(ffi.Float); -typedef NativeDecenaryOp = ffi.IntPtr Function( - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr, - ffi.IntPtr); -typedef NativeDoubleDecenaryOp = ffi.Double Function( - ffi.Double, - ffi.Double, - ffi.Double, - ffi.Double, - ffi.Double, - ffi.Double, - ffi.Double, - ffi.Double, - ffi.Double, - ffi.Double); -typedef NativeVigesimalOp = ffi.Double Function( - ffi.IntPtr, - ffi.Float, - ffi.IntPtr, - ffi.Double, - ffi.IntPtr, - ffi.Float, - ffi.IntPtr, - ffi.Double, - ffi.IntPtr, - ffi.Float, - ffi.IntPtr, - ffi.Double, - ffi.IntPtr, - ffi.Float, - ffi.IntPtr, - ffi.Double, - ffi.IntPtr, - ffi.Float, - ffi.IntPtr, - ffi.Double); -typedef Int64PointerUnOp = ffi.Pointer Function( - ffi.Pointer); +typedef NativeQuadOpSigned = Int64 Function(Int64, Int32, Int16, Int8); +typedef NativeQuadOpUnsigned = Uint64 Function(Uint64, Uint32, Uint16, Uint8); +typedef NativeFunc4 = IntPtr Function(IntPtr); +typedef NativeDoubleUnaryOp = Double Function(Double); +typedef NativeFloatUnaryOp = Float Function(Float); +typedef NativeDecenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr, + IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr); +typedef NativeDoubleDecenaryOp = Double Function(Double, Double, Double, Double, + Double, Double, Double, Double, Double, Double); +typedef NativeVigesimalOp = Double Function( + IntPtr, + Float, + IntPtr, + Double, + IntPtr, + Float, + IntPtr, + Double, + IntPtr, + Float, + IntPtr, + Double, + IntPtr, + Float, + IntPtr, + Double, + IntPtr, + Float, + IntPtr, + Double); +typedef Int64PointerUnOp = Pointer Function(Pointer); typedef QuadOp = int Function(int, int, int, int); typedef DoubleUnaryOp = double Function(double); typedef DecenaryOp = int Function( @@ -93,14 +72,14 @@ typedef VigesimalOp = double Function( int, double); -main(List arguments) { +main() { print('start main'); - ffi.DynamicLibrary ffiTestFunctions = + DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); { - // int32 bin op + // A int32 bin op. BinaryOp sumPlus42 = ffiTestFunctions.lookupFunction("SumPlus42"); @@ -110,7 +89,7 @@ main(List arguments) { } { - // various size arguments + // Various size arguments. QuadOp intComputation = ffiTestFunctions .lookupFunction("IntComputation"); var result = intComputation(125, 250, 500, 1000); @@ -124,7 +103,7 @@ main(List arguments) { } { - // unsigned int parameters + // Unsigned int parameters. QuadOp uintComputation = ffiTestFunctions .lookupFunction("UintComputation"); var result = uintComputation(0xFF, 0xFFFF, 0xFFFFFFFF, -1); @@ -135,9 +114,8 @@ main(List arguments) { } { - // architecture size argument - ffi.Pointer> p = - ffiTestFunctions.lookup("Times3"); + // Architecture size argument. + Pointer> p = ffiTestFunctions.lookup("Times3"); UnaryOp f6 = p.asFunction(); var result = f6(1337); print(result); @@ -145,7 +123,7 @@ main(List arguments) { } { - // function with double + // Function with double. DoubleUnaryOp times1_337Double = ffiTestFunctions .lookupFunction("Times1_337Double"); var result = times1_337Double(2.0); @@ -154,7 +132,7 @@ main(List arguments) { } { - // function with float + // Function with float. DoubleUnaryOp times1_337Float = ffiTestFunctions .lookupFunction("Times1_337Float"); var result = times1_337Float(1000.0); @@ -163,7 +141,7 @@ main(List arguments) { } { - // function with many arguments: arguments get passed in registers and stack + // Function with many arguments: arguments get passed in registers and stack. DecenaryOp sumManyInts = ffiTestFunctions .lookupFunction("SumManyInts"); var result = sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); @@ -172,7 +150,7 @@ main(List arguments) { } { - // function with many double arguments + // Function with many double arguments. DoubleDecenaryOp sumManyDoubles = ffiTestFunctions.lookupFunction< NativeDoubleDecenaryOp, DoubleDecenaryOp>("SumManyDoubles"); var result = @@ -182,7 +160,7 @@ main(List arguments) { } { - // function with many arguments, ints and doubles mixed + // Function with many arguments, ints and doubles mixed. VigesimalOp sumManyNumbers = ffiTestFunctions .lookupFunction("SumManyNumbers"); var result = sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, @@ -195,49 +173,49 @@ main(List arguments) { // pass an array / pointer as argument Int64PointerUnOp assign1337Index1 = ffiTestFunctions .lookupFunction("Assign1337Index1"); - ffi.Pointer p2 = allocate(count: 2); - p2.store(42); - p2.elementAt(1).store(1000); + Pointer p2 = allocate(count: 2); + p2.value = 42; + p2[1] = 1000; print(p2.elementAt(1).address.toRadixString(16)); - print(p2.elementAt(1).load()); - ffi.Pointer result = assign1337Index1(p2); - print(p2.elementAt(1).load()); + print(p2[1]); + Pointer result = assign1337Index1(p2); + print(p2[1]); print(assign1337Index1); print(assign1337Index1.runtimeType); print(result); print(result.runtimeType); print(result.address.toRadixString(16)); - print(result.load()); + print(result.value); } { - // passing in null for an int argument throws a null pointer exception + // Passing in null for an int argument throws a null pointer exception. BinaryOp sumPlus42 = ffiTestFunctions.lookupFunction("SumPlus42"); int x = null; try { sumPlus42(43, x); - } on ArgumentError { + } on Error { print('Expected exception on passing null for int'); } } { - // passing in null for a double argument throws a null pointer exception + // Passing in null for a double argument throws a null pointer exception. DoubleUnaryOp times1_337Double = ffiTestFunctions .lookupFunction("Times1_337Double"); double x = null; try { times1_337Double(x); - } on ArgumentError { + } on Error { print('Expected exception on passing null for double'); } } { - // passing in null for an int argument throws a null pointer exception + // Passing in null for an int argument throws a null pointer exception. VigesimalOp sumManyNumbers = ffiTestFunctions .lookupFunction("SumManyNumbers"); @@ -245,22 +223,22 @@ main(List arguments) { try { sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13, 14.0, 15, 16.0, 17, 18.0, x, 20.0); - } on ArgumentError { + } on Error { print('Expected exception on passing null for int'); } } { - // passing in null for a pointer argument results in a nullptr in c + // Passing in nullptr for a pointer argument results in a nullptr in c. Int64PointerUnOp nullableInt64ElemAt1 = ffiTestFunctions.lookupFunction( "NullableInt64ElemAt1"); - ffi.Pointer result = nullableInt64ElemAt1(null); + Pointer result = nullableInt64ElemAt1(nullptr); print(result); print(result.runtimeType); - ffi.Pointer p2 = allocate(count: 2); + Pointer p2 = allocate(count: 2); result = nullableInt64ElemAt1(p2); print(result); print(result.runtimeType); diff --git a/samples/ffi/sample_ffi_functions_callbacks.dart b/samples/ffi/sample_ffi_functions_callbacks.dart index 62ed355f859..affdcef8f4d 100644 --- a/samples/ffi/sample_ffi_functions_callbacks.dart +++ b/samples/ffi/sample_ffi_functions_callbacks.dart @@ -2,27 +2,26 @@ // 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. -import 'dart:ffi' as ffi; - -import 'dylib_utils.dart'; +import 'dart:ffi'; import 'coordinate.dart'; +import 'dylib_utils.dart'; -typedef NativeCoordinateOp = Coordinate Function(Coordinate); +typedef NativeCoordinateOp = Pointer Function(Pointer); -typedef CoordinateTrice = Coordinate Function( - ffi.Pointer>, Coordinate); +typedef CoordinateTrice = Pointer Function( + Pointer>, Pointer); typedef BinaryOp = int Function(int, int); -typedef NativeIntptrBinOp = ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr); -typedef NativeIntptrBinOpLookup - = ffi.Pointer> Function(); +typedef NativeIntptrBinOp = IntPtr Function(IntPtr, IntPtr); +typedef NativeIntptrBinOpLookup = Pointer> + Function(); -typedef NativeApplyTo42And74Type = ffi.IntPtr Function( - ffi.Pointer>); +typedef NativeApplyTo42And74Type = IntPtr Function( + Pointer>); typedef ApplyTo42And74Type = int Function( - ffi.Pointer>); + Pointer>); int myPlus(int a, int b) { print("myPlus"); @@ -31,51 +30,51 @@ int myPlus(int a, int b) { return a + b; } -main(List arguments) { +main() { print('start main'); - ffi.DynamicLibrary ffiTestFunctions = + DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); { - // pass a c pointer to a c function as an argument to a c function - ffi.Pointer> - transposeCoordinatePointer = + // Pass a c pointer to a c function as an argument to a c function. + Pointer> transposeCoordinatePointer = ffiTestFunctions.lookup("TransposeCoordinate"); - ffi.Pointer> p2 = + Pointer> p2 = ffiTestFunctions.lookup("CoordinateUnOpTrice"); CoordinateTrice coordinateUnOpTrice = p2.asFunction(); - Coordinate c1 = Coordinate(10.0, 20.0, null); + Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr); c1.next = c1.addressOf; - Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1); + Coordinate result = + coordinateUnOpTrice(transposeCoordinatePointer, c1.addressOf).ref; print(result.runtimeType); print(result.x); print(result.y); } { - // return a c pointer to a c function from a c function - ffi.Pointer> p14 = + // Return a c pointer to a c function from a c function. + Pointer> p14 = ffiTestFunctions.lookup("IntptrAdditionClosure"); NativeIntptrBinOpLookup intptrAdditionClosure = p14.asFunction(); - ffi.Pointer> intptrAdditionPointer = + Pointer> intptrAdditionPointer = intptrAdditionClosure(); BinaryOp intptrAddition = intptrAdditionPointer.asFunction(); print(intptrAddition(10, 27)); } { - ffi.Pointer> pointer = - ffi.Pointer.fromFunction(myPlus); + Pointer> pointer = + Pointer.fromFunction(myPlus, 0); print(pointer); - ffi.Pointer> p17 = + Pointer> p17 = ffiTestFunctions.lookup("ApplyTo42And74"); ApplyTo42And74Type applyTo42And74 = p17.asFunction(); - // int result = applyTo42And74(pointer); - // print(result); + int result = applyTo42And74(pointer); + print(result); } print("end main"); diff --git a/samples/ffi/sample_ffi_functions_structs.dart b/samples/ffi/sample_ffi_functions_structs.dart index c166b8bee60..9aefb57b2f0 100644 --- a/samples/ffi/sample_ffi_functions_structs.dart +++ b/samples/ffi/sample_ffi_functions_structs.dart @@ -2,31 +2,32 @@ // 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. -import 'dart:ffi' as ffi; - -import 'dylib_utils.dart'; +import 'dart:ffi'; import 'coordinate.dart'; +import 'dylib_utils.dart'; -typedef NativeCoordinateOp = Coordinate Function(Coordinate); +import 'package:ffi/ffi.dart'; -main(List arguments) { +typedef NativeCoordinateOp = Pointer Function(Pointer); + +main() { print('start main'); - ffi.DynamicLibrary ffiTestFunctions = + DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); { - // pass a struct to a c function and get a struct as return value - ffi.Pointer> p1 = + // Pass a struct to a c function and get a struct as return value. + Pointer> p1 = ffiTestFunctions.lookup("TransposeCoordinate"); NativeCoordinateOp f1 = p1.asFunction(); - Coordinate c1 = Coordinate(10.0, 20.0, null); - Coordinate c2 = Coordinate(42.0, 84.0, c1); + Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr); + Coordinate c2 = Coordinate.allocate(42.0, 84.0, c1.addressOf); c1.next = c2.addressOf; - Coordinate result = f1(c1); + Coordinate result = f1(c1.addressOf).ref; print(c1.x); print(c1.y); @@ -38,25 +39,25 @@ main(List arguments) { } { - // pass an array of structs to a c funtion - ffi.Pointer> p1 = + // Pass an array of structs to a c funtion. + Pointer> p1 = ffiTestFunctions.lookup("CoordinateElemAt1"); NativeCoordinateOp f1 = p1.asFunction(); - Coordinate c1 = Coordinate.allocate(count: 3); - Coordinate c2 = c1.elementAt(1); - Coordinate c3 = c1.elementAt(2); - c1.x = 10.0; - c1.y = 10.0; - c1.next = c3.addressOf; - c2.x = 20.0; - c2.y = 20.0; - c2.next = c1.addressOf; - c3.x = 30.0; - c3.y = 30.0; - c3.next = c2.addressOf; + Pointer c1 = allocate(count: 3); + Pointer c2 = c1.elementAt(1); + Pointer c3 = c1.elementAt(2); + c1.ref.x = 10.0; + c1.ref.y = 10.0; + c1.ref.next = c3; + c2.ref.x = 20.0; + c2.ref.y = 20.0; + c2.ref.next = c1; + c3.ref.x = 30.0; + c3.ref.y = 30.0; + c3.ref.next = c2; - Coordinate result = f1(c1); + Coordinate result = f1(c1).ref; print(result.x); print(result.y); diff --git a/samples/ffi/sample_ffi_structs.dart b/samples/ffi/sample_ffi_structs.dart index 471f23f64a6..bd6d7c72939 100644 --- a/samples/ffi/sample_ffi_structs.dart +++ b/samples/ffi/sample_ffi_structs.dart @@ -8,14 +8,14 @@ import 'package:ffi/ffi.dart'; import 'coordinate.dart'; -main(List arguments) { +main() { print('start main'); { - // allocates each coordinate separately in c memory - Coordinate c1 = Coordinate(10.0, 10.0, null); - Coordinate c2 = Coordinate(20.0, 20.0, c1); - Coordinate c3 = Coordinate(30.0, 30.0, c2); + // Allocates each coordinate separately in c memory. + Coordinate c1 = Coordinate.allocate(10.0, 10.0, nullptr); + Coordinate c2 = Coordinate.allocate(20.0, 20.0, c1.addressOf); + Coordinate c3 = Coordinate.allocate(30.0, 30.0, c2.addressOf); c1.next = c3.addressOf; Coordinate currentCoordinate = c1; @@ -30,31 +30,31 @@ main(List arguments) { } { - // allocates coordinates consecutively in c memory - Coordinate c1 = Coordinate.allocate(count: 3); - Coordinate c2 = c1.elementAt(1); - Coordinate c3 = c1.elementAt(2); - c1.x = 10.0; - c1.y = 10.0; - c1.next = c3.addressOf; - c2.x = 20.0; - c2.y = 20.0; - c2.next = c1.addressOf; - c3.x = 30.0; - c3.y = 30.0; - c3.next = c2.addressOf; + // Allocates coordinates consecutively in c memory. + Pointer c1 = allocate(count: 3); + Pointer c2 = c1.elementAt(1); + Pointer c3 = c1.elementAt(2); + c1.ref.x = 10.0; + c1.ref.y = 10.0; + c1.ref.next = c3; + c2.ref.x = 20.0; + c2.ref.y = 20.0; + c2.ref.next = c1; + c3.ref.x = 30.0; + c3.ref.y = 30.0; + c3.ref.next = c2; - Coordinate currentCoordinate = c1; + Coordinate currentCoordinate = c1.ref; for (var i in [0, 1, 2, 3, 4]) { currentCoordinate = currentCoordinate.next.ref; print("${currentCoordinate.x}; ${currentCoordinate.y}"); } - free(c1.addressOf); + free(c1); } { - Coordinate c = Coordinate(10, 10, null); + Coordinate c = Coordinate.allocate(10, 10, nullptr); print(c is Coordinate); print(c is Pointer); print(c is Pointer); diff --git a/samples/ffi/samples_test.dart b/samples/ffi/samples_test.dart new file mode 100644 index 00000000000..4abd4468d04 --- /dev/null +++ b/samples/ffi/samples_test.dart @@ -0,0 +1,23 @@ +// 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. +// +// This file exercises the sample files so that they are tested. +// +// SharedObjects=ffi_test_dynamic_library ffi_test_functions + +import 'sample_ffi_data.dart' as sample1; +import 'sample_ffi_dynamic_library.dart' as sample2; +import 'sample_ffi_functions_callbacks.dart' as sample3; +import 'sample_ffi_functions_structs.dart' as sample4; +import 'sample_ffi_functions.dart' as sample5; +import 'sample_ffi_structs.dart' as sample6; + +main() { + sample1.main(); + sample2.main(); + sample3.main(); + sample4.main(); + sample5.main(); + sample6.main(); +} diff --git a/samples/ffi/sqlite/docs/android.md b/samples/ffi/sqlite/docs/android.md index 7b20002d547..7478c170fbc 100644 --- a/samples/ffi/sqlite/docs/android.md +++ b/samples/ffi/sqlite/docs/android.md @@ -49,5 +49,5 @@ android { Within the `native-libraries` folder, the libraries are organized by ABI. Therefore, we must copy the compiled `libsqlite3.so` into `native-libraries/arm64-v8a/libsqlite3.so`. -If multiple sub-directories are present, the libraries from the sub-directory corresponding to the target ABI will be available in the application's linking path, so the library can be loaded with `ffi.DynamicLibrary.open("libsqlite3.so")` in Dart. +If multiple sub-directories are present, the libraries from the sub-directory corresponding to the target ABI will be available in the application's linking path, so the library can be loaded with `DynamicLibrary.open("libsqlite3.so")` in Dart. Finally, pass `--target-platform=android-arm64` to the `flutter` command when running or building the app since `libsqlite3.so` was compiled for the `arm64-v8a` ABI. diff --git a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart index fb8153af995..7304a7e4dc6 100644 --- a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart +++ b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart @@ -2,7 +2,7 @@ // 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. -import 'dart:ffi' as ffi; +import 'dart:ffi'; import 'dart:io' show Platform; String _platformPath(String name, {String path}) { @@ -14,7 +14,7 @@ String _platformPath(String name, {String path}) { throw Exception("Platform not implemented"); } -ffi.DynamicLibrary dlopenPlatformSpecific(String name, {String path}) { +DynamicLibrary dlopenPlatformSpecific(String name, {String path}) { String fullPath = _platformPath(name, path: path); - return ffi.DynamicLibrary.open(fullPath); + return DynamicLibrary.open(fullPath); } diff --git a/samples/ffi/sqlite/test/sqlite_test.dart b/samples/ffi/sqlite/test/sqlite_test.dart index 78fa39ee2a0..7bef5524de0 100644 --- a/samples/ffi/sqlite/test/sqlite_test.dart +++ b/samples/ffi/sqlite/test/sqlite_test.dart @@ -5,16 +5,17 @@ // VMOptions=--optimization-counter-threshold=5 import "dart:ffi"; +import "dart:io"; + import "package:ffi/ffi.dart"; import "package:test/test.dart"; import '../lib/sqlite.dart'; void main() { + final dbPath = Platform.script.resolve("test.db").path; test("sqlite integration test", () { - // TODO(dacoharkes): Put the database relative to this file, - // instead of where the script was invoked from. - Database d = Database("test.db"); + Database d = Database(dbPath); d.execute("drop table if exists Cookies;"); d.execute(""" create table Cookies ( @@ -107,8 +108,8 @@ void main() { }); test("concurrent db open and queries", () { - Database d = Database("test.db"); - Database d2 = Database("test.db"); + Database d = Database(dbPath); + Database d2 = Database(dbPath); d.execute("drop table if exists Cookies;"); d.execute(""" create table Cookies ( @@ -141,7 +142,7 @@ void main() { }); test("stress test", () { - Database d = Database("test.db"); + Database d = Database(dbPath); d.execute("drop table if exists Cookies;"); d.execute(""" create table Cookies ( diff --git a/samples/samples.status b/samples/samples.status index 257e3a51be3..9651dd5e78f 100644 --- a/samples/samples.status +++ b/samples/samples.status @@ -17,8 +17,11 @@ sample_extension/test/sample_extension_app_snapshot_test: Pass, RuntimeError # I [ $compiler == none && $runtime == vm && $system == fuchsia ] *: Skip # Not yet triaged. +[ $arch == simarm || $arch == simarm64 || $builder_tag == asan ] +ffi/samples_test: SkipByDesign # FFI skips, see ffi.status + [ $arch != x64 || $compiler != dartk || $system != linux || $hot_reload || $hot_reload_rollback ] -ffi/sqlite/test/sqlite_test: Skip # FFI not supported or libsqlite3.so not available. +ffi/sqlite/test/sqlite_test: SkipByDesign # FFI not supported or libsqlite3.so not available. [ $compiler == app_jitk || $compiler == dartkp ] sample_extension/test/sample_extension_app_snapshot_test: SkipByDesign