blob: 6027f61c0196320e417a360098eaec7f65221121 [file] [log] [blame]
// Copyright (c) 2024, 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:isolate';
import 'package:ffi/ffi.dart';
import 'dylib_utils.dart';
void main() async {
final myFinalizable2 = await Isolate.run(() => MyFinalizable());
print(myFinalizable2);
print(myFinalizable2.pointer);
// This would crash if a NativeFinalizer would have been attached and run
// eagerly on `Isolate.exit`.
print(myFinalizable2.pointer.value);
}
@pragma('vm:deeply-immutable')
final class MyFinalizable implements Finalizable {
final Pointer<Int> pointer;
MyFinalizable._(this.pointer);
factory MyFinalizable() {
final pointer = calloc(sizeOf<Int>(), 10).cast<Int>();
pointer.value = 123;
final result = MyFinalizable._(pointer);
newFinalizableHandle(
result,
pointer.cast(),
0,
freeFinalizer, // Not the signature of `free`!
);
return result;
}
}
final calloc = dlopenPlatformSpecific("ffi_test_functions")
.lookup<NativeFunction<Pointer<Void> Function(Size, Size)>>('Calloc')
.asFunction<Pointer<Void> Function(int, int)>();
final freeFinalizer = dlopenPlatformSpecific("ffi_test_functions")
.lookup<NativeFunction<Dart_HandleFinalizerFunction>>('FreeFinalizer');
final Dart_FinalizableHandle Function(
Object,
Pointer<Void>,
int,
Dart_HandleFinalizer,
) newFinalizableHandle = _findDartApiFunction('Dart_NewFinalizableHandle')
.cast<
NativeFunction<
Dart_FinalizableHandle Function(
Handle,
Pointer<Void>,
IntPtr,
Dart_HandleFinalizer,
)>>()
.asFunction();
final void Function(
Dart_FinalizableHandle,
Object,
) deleteFinalizableHandle = _findDartApiFunction('Dart_DeleteFinalizableHandle')
.cast<
NativeFunction<
Void Function(
Dart_FinalizableHandle,
Handle,
)>>()
.asFunction();
Pointer<Void> _findDartApiFunction(String name) {
final dartApi = NativeApi.initializeApiDLData.cast<DartApi>();
var entry = dartApi.ref.functions;
while (true) {
final entryName = entry.ref.name.cast<Utf8>().toDartString();
if (entryName == name) {
return entry.ref.function;
}
if (name == 'Dart_Null') {
throw StateError('Dart API function with $name not found.');
}
entry++;
}
}
final class DartApi extends Struct {
@Int()
external int major;
@Int()
external int minor;
external Pointer<DartApiEntry> functions;
}
final class DartApiEntry extends Struct {
external Pointer<Char> name;
external Pointer<Void> function;
}
final class _Dart_FinalizableHandle extends Opaque {}
typedef Dart_HandleFinalizer
= Pointer<NativeFunction<Dart_HandleFinalizerFunction>>;
typedef Dart_HandleFinalizerFunction = Void Function(
Pointer<Void> isolate_callback_data, Pointer<Void> peer);
typedef DartDart_HandleFinalizerFunction = void Function(
Pointer<Void> isolate_callback_data, Pointer<Void> peer);
typedef Dart_FinalizableHandle = Pointer<_Dart_FinalizableHandle>;