| // Copyright (c) 2022, 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. |
| // |
| // SharedObjects=ffi_test_functions |
| |
| import 'dart:ffi'; |
| import 'dart:io'; |
| |
| import 'ffi_test_helpers.dart'; |
| |
| void main() { |
| testMallocFree(); |
| print('end of test, shutting down'); |
| } |
| |
| void testMallocFree() { |
| if (Platform.isWindows) { |
| // malloc and free not supported. |
| return; |
| } |
| |
| print('freePtr $freePtr'); |
| |
| { |
| final resource = MyNativeResource(); |
| resource.close(); |
| doGC(); |
| } |
| |
| { |
| MyNativeResource(); |
| doGC(); |
| } |
| |
| // Run finalizer on shutdown (or on a GC that runs before shutdown). |
| MyNativeResource(); |
| } |
| |
| class MyNativeResource implements Finalizable { |
| final Pointer<Void> pointer; |
| |
| bool _closed = false; |
| |
| MyNativeResource._(this.pointer, {int? externalSize}) { |
| print('pointer $pointer'); |
| freeFinalizer.attach( |
| this, |
| pointer, |
| externalSize: externalSize, |
| detach: this, |
| ); |
| } |
| |
| factory MyNativeResource() { |
| const num = 1; |
| const size = 16; |
| final pointer = calloc(num, size); |
| return MyNativeResource._(pointer, externalSize: size); |
| } |
| |
| /// Eagerly stop using the native resource. Cancelling the finalizer. |
| void close() { |
| _closed = true; |
| freeFinalizer.detach(this); |
| free(pointer); |
| } |
| |
| void useResource() { |
| if (_closed) { |
| throw UnsupportedError('The native resource has already been released'); |
| } |
| print(pointer.address); |
| } |
| } |
| |
| final DynamicLibrary stdlib = DynamicLibrary.process(); |
| |
| typedef PosixCallocNative = Pointer<Void> Function(IntPtr num, IntPtr size); |
| typedef PosixCalloc = Pointer<Void> Function(int num, int size); |
| final PosixCalloc calloc = stdlib |
| .lookupFunction<PosixCallocNative, PosixCalloc>('calloc'); |
| |
| typedef PosixFreeNative = Void Function(Pointer<Void>); |
| final freePtr = stdlib.lookup<NativeFunction<PosixFreeNative>>('free'); |
| final free = freePtr.asFunction<void Function(Pointer<Void>)>(); |
| |
| final freeFinalizer = NativeFinalizer(freePtr); |