// 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 /// Foreign Function Interface for interoperability with the C programming language. /// /// For further details, please see: https://dart.dev/server/c-interop. /// /// {@category VM} @Since('2.6') library dart.ffi; import 'dart:_internal' show Since; import 'dart:isolate'; import 'dart:typed_data'; part 'abi.dart'; part 'abi_specific.dart'; part 'native_type.dart'; part 'native_finalizer.dart'; part 'allocation.dart'; part 'annotations.dart'; part 'c_type.dart'; part 'dynamic_library.dart'; part 'struct.dart'; part 'union.dart'; /// Number of bytes used by native type T. /// /// Includes padding and alignment of structs. /// /// This function must be invoked with a compile-time constant [T]. external int sizeOf(); /// Represents a pointer into the native C memory corresponding to 'NULL', e.g. /// a pointer with address 0. @pragma('vm:shared') final Pointer nullptr = Pointer.fromAddress(0); /// Represents a pointer into the native C memory. Cannot be extended. @pragma('vm:entry-point') @pragma("wasm:entry-point") final class Pointer implements SizedNativeType { /// Construction from raw integer. external factory Pointer.fromAddress(int ptr); /// Convert Dart function to a C function pointer, automatically marshalling /// the arguments and return value /// /// If an exception is thrown while calling `f()`, the native function will /// return `exceptionalReturn`, which must be assignable to return type of `f`. /// /// The returned function address can only be invoked on the mutator (main) /// thread of the current isolate. It will abort the process if invoked on any /// other thread. Use [NativeCallable.listener] to create callbacks that can /// be invoked from any thread. /// /// The pointer returned will remain alive for the duration of the current /// isolate's lifetime. After the isolate it was created in is terminated, /// invoking it from native code will cause undefined behavior. /// /// [Pointer.fromFunction] only accepts static or top level functions. Use /// [NativeCallable.isolateLocal] to create callbacks from any Dart function /// or closure. external static Pointer> fromFunction( @DartRepresentationOf('T') Function f, [ Object? exceptionalReturn, ]); /// Access to the raw pointer value. /// On 32-bit systems, the upper 32-bits of the result are 0. external int get address; /// Reinterprets the address of this pointer as the address of a [U]. /// /// This function is completely unchecked, no attempts are made to validate /// that the bytes at the address are actually a valid native value /// of type [U]. external Pointer cast(); /// Equality for Pointers only depends on their address. bool operator ==(Object other) { if (other is! Pointer) return false; Pointer otherPointer = other; return address == otherPointer.address; } /// The hash code for a Pointer only depends on its address. int get hashCode { return address.hashCode; } } /// A fixed-sized array of [T]s. @Since('2.13') final class Array extends _Compound { /// Annotation to specify [Array] dimensions in [Struct]s. /// /// ```dart /// final class MyStruct extends Struct { /// @Array(8) /// external Array inlineArray; /// /// @Array(2, 2, 2) /// external Array>> threeDimensionalInlineArray; /// } /// ``` /// /// Do not invoke in normal code. const factory Array( int dimension1, [ int dimension2, int dimension3, int dimension4, int dimension5, ]) = _ArraySize; /// Annotation to specify [Array] dimensions in [Struct]s. /// /// ```dart /// final class MyStruct extends Struct { /// @Array.multi([2, 2, 2]) /// external Array>> threeDimensionalInlineArray; /// /// @Array.multi([2, 2, 2, 2, 2, 2, 2, 2]) /// external Array>>>>>>> eightDimensionalInlineArray; /// } /// ``` /// /// Do not invoke in normal code. const factory Array.multi(List dimensions) = _ArraySize.multi; /// Annotation to specify a variable length [Array] in [Struct]s. /// /// Can only be used on the last field of a struct. The last field of the /// struct is _not_ taken into account in [sizeOf]. Using an /// [AllocatorAlloc.call] will _not_ allocate any backing storage for the /// variable length array. Instead use [Allocator.allocate] and calculate the /// required number of bytes manually. /// /// ```dart /// import 'dart:ffi'; /// import 'package:ffi/ffi.dart'; /// /// final class MyStruct extends Struct { /// @Size() /// external int length; /// /// @Array.variable() /// external Array inlineArray; /// /// static Pointer allocate(Allocator allocator, int length) { /// final lengthInBytes = sizeOf() + sizeOf() * length; /// final result = allocator.allocate(lengthInBytes); /// result.ref.length = length; /// return result; /// } /// } /// /// void main() { /// final myStruct = MyStruct.allocate(calloc, 10); /// } /// ``` /// /// The variable length is always the outermost dimension of the array. /// /// ```dart /// import 'dart:ffi'; /// import 'package:ffi/ffi.dart'; /// /// final class MyStruct extends Struct { /// @Size() /// external int length; /// /// @Array.variable(10, 10) /// external Array>> inlineArray; /// /// static Pointer allocate(Allocator allocator, int length) { /// final lengthInBytes = sizeOf() + sizeOf() * length * 100; /// final result = allocator.allocate(lengthInBytes); /// result.ref.length = length; /// return result; /// } /// } /// ``` /// /// Accessing variable length inline arrays of structs passed by value in FFI /// calls and callbacks is undefined behavior. Accessing variable length /// inline arrays in structs passed by value is undefined behavior in C. /// /// For more information about variable length inline arrays in C, please /// refer to: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html. /// /// Do not invoke in normal code. @Since('3.6') const factory Array.variable([ int dimension2, int dimension3, int dimension4, int dimension5, ]) = _ArraySize.variable; /// Annotation to specify a variable length [Array] with a configurable /// variable dimension ([dimension1]) in [Struct]s. /// /// Can only be used on the last field of a struct. When [dimension1] is set /// to a value greater than zero (`0`), the last field of the struct is taken /// into account in [sizeOf] and [AllocatorAlloc.call]. This is particularly /// useful when working with Windows APIs, where most structs with variable /// length arrays are defined to have an initial dimension of one (`1`). /// /// ```dart /// import 'dart:ffi'; /// import 'package:ffi/ffi.dart'; /// /// final class MyStruct extends Struct { /// @Size() /// external int length; /// /// @Array.variableWithVariableDimension(1) /// external Array inlineArray; /// /// static Pointer allocate(Allocator allocator, int length) { /// final lengthInBytes = sizeOf() + sizeOf() * (length - 1); /// final result = allocator.allocate(lengthInBytes); /// result.ref.length = length; /// return result; /// } /// } /// /// void main() { /// final myStruct = MyStruct.allocate(calloc, 10); /// } /// ``` /// /// The variable length is always the outermost dimension of the array. /// /// Do not invoke in normal code. @Since('3.7') const factory Array.variableWithVariableDimension([ int dimension1, int dimension2, int dimension3, int dimension4, int dimension5, ]) = _ArraySize.variableWithVariableDimension; /// Annotation to a variable length [Array] in [Struct]s. /// /// ```dart /// final class MyStruct extends Struct { /// @Array.variableMulti([2, 2]) /// external Array>> threeDimensionalInlineArray; /// } /// /// final class MyStruct2 extends Struct { /// @Array.variableMulti(variableDimension: 1, [2, 2, 2]) /// external Array>>> fourDimensionalInlineArray; /// } /// /// final class MyStruct3 extends Struct { /// @Array.variableMulti([2, 2, 2, 2, 2, 2, 2]) /// external Array>>>>>>> eightDimensionalInlineArray; /// } /// ``` /// /// The variable length is always the outermost dimension of the array. /// /// [variableDimension] is the outermost dimension of the variable length /// array (defaults to zero (`0`)). When [variableDimension] is set to a value /// greater than zero (`0`), the last field of the struct is taken into /// account in [sizeOf] and [AllocatorAlloc.call]. /// /// Do not invoke in normal code. @Since('3.6') const factory Array.variableMulti( List dimensions, { @Since('3.7') int variableDimension, }) = _ArraySize.variableMulti; } final class _ArraySize implements Array { final int? dimension1; final int? dimension2; final int? dimension3; final int? dimension4; final int? dimension5; final List? dimensions; // When non-null, [dimension1] is equal to this value, or [dimensions] should // be prepended with this value. final int? variableDimension; const _ArraySize( this.dimension1, [ this.dimension2, this.dimension3, this.dimension4, this.dimension5, ]) : dimensions = null, variableDimension = null; const _ArraySize.multi(this.dimensions) : dimension1 = null, dimension2 = null, dimension3 = null, dimension4 = null, dimension5 = null, variableDimension = null; const _ArraySize.variable([ this.dimension2, this.dimension3, this.dimension4, this.dimension5, ]) : dimension1 = 0, dimensions = null, variableDimension = 0; const _ArraySize.variableWithVariableDimension([ this.dimension1, this.dimension2, this.dimension3, this.dimension4, this.dimension5, ]) : dimensions = null, variableDimension = dimension1; const _ArraySize.variableMulti( List nestedDimensions, { int variableDimension = 0, }) : // Should be `[variableDimension, ...nestedDimensions]`. dimensions = nestedDimensions, dimension1 = null, dimension2 = null, dimension3 = null, dimension4 = null, dimension5 = null, variableDimension = variableDimension; } /// Extension on [Pointer] specialized for the type argument [NativeFunction]. extension NativeFunctionPointer on Pointer> { /// Convert to Dart function, automatically marshalling the arguments and /// return value. /// /// [isLeaf] specifies whether the function is a leaf function. Leaf functions /// are small, short-running, non-blocking functions which are not allowed to /// call back into Dart or use any Dart VM APIs. Leaf functions are invoked /// bypassing some of the heavier parts of the standard Dart-to-Native calling /// sequence which reduces the invocation overhead, making leaf calls faster /// than non-leaf calls. However, this implies that a thread executing a leaf /// function can't cooperate with the Dart runtime. A long running or blocking /// leaf function will delay any operation which requires synchronization /// between all threads associated with an isolate group until after the leaf /// function returns. For example, if one isolate in a group is trying to /// perform a GC and a second isolate is blocked in a leaf call, then the /// first isolate will have to pause and wait until this leaf call returns. external DF asFunction<@DartRepresentationOf('NF') DF extends Function>({ bool isLeaf = false, }); } /// A native callable which listens for calls to a native function. /// /// Creates a native function linked to a Dart function, so that calling the /// native function will call the Dart function in some way, with the arguments /// converted to Dart values. @Since('3.1') abstract final class NativeCallable { /// Constructs a [NativeCallable] that must be invoked from the same thread /// that created it. /// /// If an exception is thrown by the [callback], the native function will /// return the `exceptionalReturn`, which must be assignable to the return /// type of the [callback]. /// /// The returned function address can only be invoked on the mutator (main) /// thread of the current isolate. It will abort the process if invoked on any /// other thread. Use [NativeCallable.listener] to create callbacks that can /// be invoked from any thread. /// /// Unlike [Pointer.fromFunction], [NativeCallable]s can be constructed from /// any Dart function or closure, not just static or top level functions. /// /// This callback must be [close]d when it is no longer needed. The [Isolate] /// that created the callback will be kept alive until [close] is called. /// After [NativeCallable.close] is called, invoking the [nativeFunction] from /// native code will cause undefined behavior. factory NativeCallable.isolateLocal( @DartRepresentationOf("T") Function callback, { Object? exceptionalReturn, }) { throw UnsupportedError("NativeCallable cannot be constructed dynamically."); } /// Constructs a [NativeCallable] that can be invoked from any thread. /// /// When the native code invokes the function [nativeFunction], /// the [callback] will be executed within the isolate group /// of the [Isolate] which originally constructed the callable. /// Specifically, this means that an attempt to access any /// static or global field which is not shared between /// isolates in a group will result in a [Error]. /// /// If an exception is thrown by the [callback], the /// native function will return the `exceptionalReturn`, /// which must be assignable to the return type of /// the [callback]. /// /// [callback] and [exceptionalReturn] must be /// _trivially shareable_. /// /// This callback must be [close]d when it is no longer /// needed. An [Isolate] that created the callback will /// be kept alive until [close] is called. /// /// After [NativeCallable.close] is called, invoking /// the [nativeFunction] from native code will cause /// undefined behavior. /// /// NOTE: This is an experimental feature and may change in the future. factory NativeCallable.isolateGroupBound( @DartRepresentationOf("T") Function callback, { Object? exceptionalReturn, }) { throw UnsupportedError("NativeCallable cannot be constructed dynamically."); } /// Constructs a [NativeCallable] that can be invoked from any thread. /// /// When the native code invokes the function [nativeFunction], the arguments /// will be sent over a [SendPort] to the [Isolate] that created the /// [NativeCallable], and the callback will be invoked. /// /// The native code does not wait for a response from the callback, so only /// functions returning void are supported. /// /// The callback will be invoked at some time in the future. The native caller /// cannot assume the callback will be run immediately. Resources passed to /// the callback (such as pointers to malloc'd memory, or output parameters) /// must be valid until the call completes. /// /// This callback must be [close]d when it is no longer needed. The [Isolate] /// that created the callback will be kept alive until [close] is called. /// After [NativeCallable.close] is called, invoking the [nativeFunction] from /// native code will cause undefined behavior. /// /// For example: /// /// ```dart /// import 'dart:async'; /// import 'dart:ffi'; /// import 'package:ffi/ffi.dart'; /// /// // Processes a simple HTTP GET request using a native HTTP library that /// // processes the request on a background thread. /// Future httpGet(String uri) async { /// final uriPointer = uri.toNativeUtf8(); /// /// // Create the NativeCallable.listener. /// final completer = Completer(); /// late final NativeCallable callback; /// void onResponse(Pointer responsePointer) { /// completer.complete(responsePointer.toDartString()); /// calloc.free(responsePointer); /// calloc.free(uriPointer); /// /// // Remember to close the NativeCallable once the native API is /// // finished with it, otherwise this isolate will stay alive /// // indefinitely. /// callback.close(); /// } /// callback = NativeCallable.listener(onResponse); /// /// // Invoke the native HTTP API. Our example HTTP library processes our /// // request on a background thread, and calls the callback on that same /// // thread when it receives the response. /// nativeHttpGet(uriPointer, callback.nativeFunction); /// /// return completer.future; /// } /// /// // Load the native functions from a DynamicLibrary. /// final DynamicLibrary dylib = DynamicLibrary.process(); /// typedef NativeHttpCallback = Void Function(Pointer); /// /// typedef HttpGetFunction = void Function( /// Pointer, Pointer>); /// typedef HttpGetNativeFunction = Void Function( /// Pointer, Pointer>); /// final nativeHttpGet = /// dylib.lookupFunction( /// 'http_get'); /// ``` factory NativeCallable.listener( @DartRepresentationOf("T") Function callback, ) { throw UnsupportedError("NativeCallable cannot be constructed dynamically."); } /// The native function pointer which can be used to invoke the `callback` /// passed to the constructor. /// /// This pointer must not be read after the callable has been [close]d. Pointer> get nativeFunction; /// Closes this callback and releases its resources. /// /// Further calls to existing [nativeFunction]s will result in undefined /// behavior. /// /// Subsequent calls to [close] will be ignored. /// /// It is safe to call [close] inside the [callback]. void close(); /// Whether this [NativeCallable] keeps its [Isolate] alive. /// /// By default, [NativeCallable]s keep the [Isolate] that created them alive /// until [close] is called. If [keepIsolateAlive] is set to `false`, the /// isolate may exit even if the [NativeCallable] isn't closed. external bool get keepIsolateAlive; external set keepIsolateAlive(bool value); } // // Generated code, do not edit! // // Code generated by `runtime/tools/ffi/sdk_lib_ffi_generator.dart`. // /// Extension on [Pointer] specialized for the type argument [Int8]. extension Int8Pointer on Pointer { /// The 8-bit two's complement integer at [address]. /// /// A Dart integer is truncated to 8 bits (as if by `.toSigned(8)`) before /// being stored, and the 8-bit value is sign-extended when it is loaded. external int get value; external void set value(int value); /// The 8-bit two's complement integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 8 bits (as if by `.toSigned(8)`) before /// being stored, and the 8-bit value is sign-extended when it is loaded. external int operator [](int index); /// The 8-bit two's complement integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 8 bits (as if by `.toSigned(8)`) before /// being stored, and the 8-bit value is sign-extended when it is loaded. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Int8] after this one. /// /// Returns a pointer to the [Int8] whose address is /// [offset] times the size of `Int8` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Int8] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Int8] whose address is /// [offset] times the size of `Int8` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. external Int8List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Int16]. extension Int16Pointer on Pointer { /// The 16-bit two's complement integer at [address]. /// /// A Dart integer is truncated to 16 bits (as if by `.toSigned(16)`) before /// being stored, and the 16-bit value is sign-extended when it is loaded. /// /// The [address] must be 2-byte aligned. external int get value; external void set value(int value); /// The 16-bit two's complement integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 16 bits (as if by `.toSigned(16)`) before /// being stored, and the 16-bit value is sign-extended when it is loaded. /// /// The [address] must be 2-byte aligned. external int operator [](int index); /// The 16-bit two's complement integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 16 bits (as if by `.toSigned(16)`) before /// being stored, and the 16-bit value is sign-extended when it is loaded. /// /// The [address] must be 2-byte aligned. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Int16] after this one. /// /// Returns a pointer to the [Int16] whose address is /// [offset] times the size of `Int16` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Int16] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Int16] whose address is /// [offset] times the size of `Int16` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 2-byte aligned. external Int16List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Int32]. extension Int32Pointer on Pointer { /// The 32-bit two's complement integer at [address]. /// /// A Dart integer is truncated to 32 bits (as if by `.toSigned(32)`) before /// being stored, and the 32-bit value is sign-extended when it is loaded. /// /// The [address] must be 4-byte aligned. external int get value; external void set value(int value); /// The 32-bit two's complement integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 32 bits (as if by `.toSigned(32)`) before /// being stored, and the 32-bit value is sign-extended when it is loaded. /// /// The [address] must be 4-byte aligned. external int operator [](int index); /// The 32-bit two's complement integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 32 bits (as if by `.toSigned(32)`) before /// being stored, and the 32-bit value is sign-extended when it is loaded. /// /// The [address] must be 4-byte aligned. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Int32] after this one. /// /// Returns a pointer to the [Int32] whose address is /// [offset] times the size of `Int32` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Int32] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Int32] whose address is /// [offset] times the size of `Int32` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 4-byte aligned. external Int32List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Int64]. extension Int64Pointer on Pointer { /// The 64-bit two's complement integer at [address]. /// /// The [address] must be 8-byte aligned. external int get value; external void set value(int value); /// The 64-bit two's complement integer at `address + sizeOf() * index`. /// /// The [address] must be 8-byte aligned. external int operator [](int index); /// The 64-bit two's complement integer at `address + sizeOf() * index`. /// /// The [address] must be 8-byte aligned. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Int64] after this one. /// /// Returns a pointer to the [Int64] whose address is /// [offset] times the size of `Int64` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Int64] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Int64] whose address is /// [offset] times the size of `Int64` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 8-byte aligned. external Int64List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Uint8]. extension Uint8Pointer on Pointer { /// The 8-bit unsigned integer at [address]. /// /// A Dart integer is truncated to 8 bits (as if by `.toUnsigned(8)`) before /// being stored, and the 8-bit value is zero-extended when it is loaded. external int get value; external void set value(int value); /// The 8-bit unsigned integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 8 bits (as if by `.toUnsigned(8)`) before /// being stored, and the 8-bit value is zero-extended when it is loaded. external int operator [](int index); /// The 8-bit unsigned integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 8 bits (as if by `.toUnsigned(8)`) before /// being stored, and the 8-bit value is zero-extended when it is loaded. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Uint8] after this one. /// /// Returns a pointer to the [Uint8] whose address is /// [offset] times the size of `Uint8` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Uint8] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Uint8] whose address is /// [offset] times the size of `Uint8` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. external Uint8List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Uint16]. extension Uint16Pointer on Pointer { /// The 16-bit unsigned integer at [address]. /// /// A Dart integer is truncated to 16 bits (as if by `.toUnsigned(16)`) before /// being stored, and the 16-bit value is zero-extended when it is loaded. /// /// The [address] must be 2-byte aligned. external int get value; external void set value(int value); /// The 16-bit unsigned integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 16 bits (as if by `.toUnsigned(16)`) before /// being stored, and the 16-bit value is zero-extended when it is loaded. /// /// The [address] must be 2-byte aligned. external int operator [](int index); /// The 16-bit unsigned integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 16 bits (as if by `.toUnsigned(16)`) before /// being stored, and the 16-bit value is zero-extended when it is loaded. /// /// The [address] must be 2-byte aligned. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Uint16] after this one. /// /// Returns a pointer to the [Uint16] whose address is /// [offset] times the size of `Uint16` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Uint16] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Uint16] whose address is /// [offset] times the size of `Uint16` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 2-byte aligned. external Uint16List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Uint32]. extension Uint32Pointer on Pointer { /// The 32-bit unsigned integer at [address]. /// /// A Dart integer is truncated to 32 bits (as if by `.toUnsigned(32)`) before /// being stored, and the 32-bit value is zero-extended when it is loaded. /// /// The [address] must be 4-byte aligned. external int get value; external void set value(int value); /// The 32-bit unsigned integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 32 bits (as if by `.toUnsigned(32)`) before /// being stored, and the 32-bit value is zero-extended when it is loaded. /// /// The [address] must be 4-byte aligned. external int operator [](int index); /// The 32-bit unsigned integer at `address + sizeOf() * index`. /// /// A Dart integer is truncated to 32 bits (as if by `.toUnsigned(32)`) before /// being stored, and the 32-bit value is zero-extended when it is loaded. /// /// The [address] must be 4-byte aligned. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Uint32] after this one. /// /// Returns a pointer to the [Uint32] whose address is /// [offset] times the size of `Uint32` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Uint32] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Uint32] whose address is /// [offset] times the size of `Uint32` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 4-byte aligned. external Uint32List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Uint64]. extension Uint64Pointer on Pointer { /// The 64-bit unsigned integer at [address]. /// /// The [address] must be 8-byte aligned. external int get value; external void set value(int value); /// The 64-bit unsigned integer at `address + sizeOf() * index`. /// /// The [address] must be 8-byte aligned. external int operator [](int index); /// The 64-bit unsigned integer at `address + sizeOf() * index`. /// /// The [address] must be 8-byte aligned. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Uint64] after this one. /// /// Returns a pointer to the [Uint64] whose address is /// [offset] times the size of `Uint64` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Uint64] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Uint64] whose address is /// [offset] times the size of `Uint64` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 8-byte aligned. external Uint64List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Float]. extension FloatPointer on Pointer { /// The float at [address]. /// /// A Dart double loses precision before being stored, and the float value is /// converted to a double when it is loaded. /// /// The [address] must be 4-byte aligned. external double get value; external void set value(double value); /// The float at `address + sizeOf() * index`. /// /// A Dart double loses precision before being stored, and the float value is /// converted to a double when it is loaded. /// /// The [address] must be 4-byte aligned. external double operator [](int index); /// The float at `address + sizeOf() * index`. /// /// A Dart double loses precision before being stored, and the float value is /// converted to a double when it is loaded. /// /// The [address] must be 4-byte aligned. external void operator []=(int index, double value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Float] after this one. /// /// Returns a pointer to the [Float] whose address is /// [offset] times the size of `Float` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Float] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Float] whose address is /// [offset] times the size of `Float` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 4-byte aligned. external Float32List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Double]. extension DoublePointer on Pointer { /// The double at [address]. /// /// The [address] must be 8-byte aligned. external double get value; external void set value(double value); /// The double at `address + sizeOf() * index`. /// /// The [address] must be 8-byte aligned. external double operator [](int index); /// The double at `address + sizeOf() * index`. /// /// The [address] must be 8-byte aligned. external void operator []=(int index, double value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Double] after this one. /// /// Returns a pointer to the [Double] whose address is /// [offset] times the size of `Double` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Double] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Double] whose address is /// [offset] times the size of `Double` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); /// Creates a typed list view backed by memory in the address space. /// /// The returned view will allow access to the memory range from [address] /// to `address + sizeOf() * length`. /// /// The user has to ensure the memory range is accessible while using the /// returned list. /// /// If provided, [finalizer] will be run on the pointer once the typed list /// is GCed. If provided, [token] will be passed to [finalizer], otherwise /// the this pointer itself will be passed. /// /// The [address] must be 8-byte aligned. external Float64List asTypedList( int length, { @Since('3.1') Pointer? finalizer, @Since('3.1') Pointer? token, }); } /// Extension on [Pointer] specialized for the type argument [Bool]. @Since('2.15') extension BoolPointer on Pointer { /// The bool at [address]. external bool get value; external void set value(bool value); /// The bool at `address + sizeOf() * index`. external bool operator [](int index); /// The bool at `address + sizeOf() * index`. external void operator []=(int index, bool value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') Pointer elementAt(int index) => Pointer.fromAddress(address + sizeOf() * index); /// A pointer to the [offset]th [Bool] after this one. /// /// Returns a pointer to the [Bool] whose address is /// [offset] times the size of `Bool` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. @Since('3.3') @pragma("vm:prefer-inline") Pointer operator +(int offset) => Pointer.fromAddress(address + sizeOf() * offset); /// A pointer to the [offset]th [Bool] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Bool] whose address is /// [offset] times the size of `Bool` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, @Since('3.3') @pragma("vm:prefer-inline") Pointer operator -(int offset) => Pointer.fromAddress(address - sizeOf() * offset); } /// Bounds checking indexing methods on [Array]s of [Int8]. @Since('2.13') extension Int8Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Int8List get elements; } /// Bounds checking indexing methods on [Array]s of [Int16]. @Since('2.13') extension Int16Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Int16List get elements; } /// Bounds checking indexing methods on [Array]s of [Int32]. @Since('2.13') extension Int32Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Int32List get elements; } /// Bounds checking indexing methods on [Array]s of [Int64]. @Since('2.13') extension Int64Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Int64List get elements; } /// Bounds checking indexing methods on [Array]s of [Uint8]. @Since('2.13') extension Uint8Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Uint8List get elements; } /// Bounds checking indexing methods on [Array]s of [Uint16]. @Since('2.13') extension Uint16Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Uint16List get elements; } /// Bounds checking indexing methods on [Array]s of [Uint32]. @Since('2.13') extension Uint32Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Uint32List get elements; } /// Bounds checking indexing methods on [Array]s of [Uint64]. @Since('2.13') extension Uint64Array on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Uint64List get elements; } /// Bounds checking indexing methods on [Array]s of [Float]. @Since('2.13') extension FloatArray on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external double operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, double value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Float32List get elements; } /// Bounds checking indexing methods on [Array]s of [Double]. @Since('2.13') extension DoubleArray on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external double operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, double value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external Float64List get elements; } /// Bounds checking indexing methods on [Array]s of [Bool]. @Since('2.15') extension BoolArray on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external bool operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, bool value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external List get elements; } @Since('3.5') extension Int8ListAddress on Int8List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Int8List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Int16ListAddress on Int16List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Int16List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Int32ListAddress on Int32List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Int32List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Int64ListAddress on Int64List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Int64List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Uint8ListAddress on Uint8List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Uint8List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Uint16ListAddress on Uint16List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Uint16List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Uint32ListAddress on Uint32List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Uint32List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Uint64ListAddress on Uint64List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Uint64List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Float32ListAddress on Float32List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Float32List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension Float64ListAddress on Float64List { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` /// can only occurr as an entire argument expression in the invocation of /// a leaf [Native] external function. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// void main() { /// final list = Float64List(10); /// myFunction(list.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } // // End of generated code. // /// Extension on [Pointer] specialized for the type argument [Pointer]. extension PointerPointer on Pointer> { /// The pointer at [address]. /// /// A [Pointer] is unboxed before being stored (as if by `.address`), and the /// pointer is boxed (as if by `Pointer.fromAddress`) when loaded. /// /// On 32-bit platforms the [address] must be 4-byte aligned, and on 64-bit /// platforms the [address] must be 8-byte aligned. external Pointer get value; external void set value(Pointer value); /// Load a Dart value from this location offset by [index]. /// /// A [Pointer] is unboxed before being stored (as if by `.address`), and the /// pointer is boxed (as if by `Pointer.fromAddress`) when loaded. /// /// On 32-bit platforms the [address] must be 4-byte aligned, and on 64-bit /// platforms the [address] must be 8-byte aligned. external Pointer operator [](int index); /// Store a Dart value into this location offset by [index]. /// /// A [Pointer] is unboxed before being stored (as if by `.address`), and the /// pointer is boxed (as if by [Pointer.fromAddress]) when loaded. /// /// On 32-bit platforms the [address] must be 4-byte aligned, and on 64-bit /// platforms the [address] must be 8-byte aligned. external void operator []=(int index, Pointer value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') external Pointer> elementAt(int index); /// A pointer to the [offset]th [Pointer] after this one. /// /// Returns a pointer to the [Pointer] whose address is /// [offset] times the size of `Pointer` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf>()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. external Pointer> operator +(int offset); /// A pointer to the [offset]th [Pointer] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [Pointer] whose address is /// [offset] times the size of `Pointer` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf>()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, external Pointer> operator -(int offset); } /// Extension on [Pointer] specialized for the type argument [Struct]. extension StructPointer on Pointer { /// A Dart view of the struct referenced by this pointer. /// /// Reading [ref] creates a reference accessing the fields of this struct /// backed by native memory at [address]. /// The [address] must be aligned according to the struct alignment rules of /// the platform. /// /// Assigning to [ref] copies contents of the struct into the native memory /// starting at [address]. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external T get ref; external set ref(T value); /// A Dart view of the struct referenced by this pointer. /// /// Creates a reference accessing the fields of this struct backed by native /// memory at [address]. /// The [address] must be aligned according to the struct alignment rules of /// the platform. /// /// Attaches [finalizer] to the backing store of the struct. If provided, /// [token] will be passed to [finalizer], otherwise the pointer (`this`) /// itself will be passed. /// The pointer (`this`) must _not_ be used anymore if the struct is _not_ /// guaranteed to be kept alive. /// Prefer doing any native calls with the pointer _before_ calling /// [refWithFinalizer]. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. @Since('3.7') external T refWithFinalizer( Pointer finalizer, { Pointer? token, }); /// Creates a reference to access the fields of this struct backed by native /// memory at `address + sizeOf() * index`. /// /// The [address] must be aligned according to the struct alignment rules of /// the platform. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external T operator [](int index); /// Copies the [value] struct into native memory, starting at /// `address * sizeOf() * index`. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external void operator []=(int index, T value); /// Pointer arithmetic (takes element size into account) @Deprecated('Use operator + instead') external Pointer elementAt(int index); /// A pointer to the [offset]th [T] after this one. /// /// Returns a pointer to the [T] whose address is /// [offset] times the size of `T` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. external Pointer operator +(int offset); /// A pointer to the [offset]th [T] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [T] whose address is /// [offset] times the size of `T` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, external Pointer operator -(int offset); } /// Extension on [Pointer] specialized for the type argument [Union]. @Since('2.14') extension UnionPointer on Pointer { /// A Dart view of the union referenced by this pointer. /// /// Reading [ref] creates a reference accessing the fields of this union /// backed by native memory at [address]. /// The [address] must be aligned according to the union alignment rules of /// the platform. /// /// Assigning to [ref] copies contents of the union into the native memory /// starting at [address]. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external T get ref; external set ref(T value); /// A Dart view of the union referenced by this pointer. /// /// Creates a reference accessing the fields of this union backed by native /// memory at [address]. /// The [address] must be aligned according to the union alignment rules of /// the platform. /// /// Attaches [finalizer] to the backing store of the union. If provided, /// [token] will be passed to [finalizer], otherwise the pointer (`this`) /// itself will be passed. /// The pointer (`this`) must _not_ be used anymore if the union is _not_ /// guaranteed to be kept alive. /// Prefer doing any native calls with the pointer _before_ calling /// [refWithFinalizer]. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. @Since('3.7') external T refWithFinalizer( Pointer finalizer, { Pointer? token, }); /// Creates a reference to access the fields of this union backed by native /// memory at `address + sizeOf() * index`. /// /// The [address] must be aligned according to the union alignment rules of /// the platform. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external T operator [](int index); /// Copies the [value] union into native memory, starting at /// `address * sizeOf() * index`. /// /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external void operator []=(int index, T value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') external Pointer elementAt(int index); /// A pointer to the [offset]th [T] after this one. /// /// Returns a pointer to the [T] whose address is /// [offset] times the size of `T` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. external Pointer operator +(int offset); /// A pointer to the [offset]th [T] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [T] whose address is /// [offset] times the size of `T` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, external Pointer operator -(int offset); } /// Extension on [Pointer] specialized for the type argument /// [AbiSpecificInteger]. @Since('2.16') extension AbiSpecificIntegerPointer on Pointer { /// The integer at [address]. external int get value; external void set value(int value); /// The integer at `address + sizeOf() * index`. external int operator [](int index); /// The integer at `address + sizeOf() * index`. external void operator []=(int index, int value); /// Pointer arithmetic (takes element size into account). @Deprecated('Use operator + instead') external Pointer elementAt(int index); /// A pointer to the [offset]th [T] after this one. /// /// Returns a pointer to the [T] whose address is /// [offset] times the size of `T` after the address of this pointer. /// That is `(this + offset).address == this.address + offset * sizeOf()`. /// /// Also `(this + offset).value` is equivalent to `this[offset]`, /// and similarly for setting. external Pointer operator +(int offset); /// A pointer to the [offset]th [T] before this one. /// /// Equivalent to `this + (-offset)`. /// /// Returns a pointer to the [T] whose address is /// [offset] times the size of `T` before the address of this pointer. /// That is, `(this - offset).address == this.address - offset * sizeOf()`. /// /// Also, `(this - offset).value` is equivalent to `this[-offset]`, /// and similarly for setting, external Pointer operator -(int offset); } /// Bounds checking indexing methods on [Array]s of [Pointer]. @Since('2.13') extension PointerArray on Array> { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external Pointer operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, Pointer value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external List> get elements; } /// Bounds checking indexing methods on [Array]s of [Struct]. @Since('2.13') extension StructArray on Array { /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external T operator [](int index); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array. @Since('3.8') external List get elements; } /// Bounds checking indexing methods on [Array]s of [Union]. @Since('2.14') extension UnionArray on Array { /// This extension method must be invoked on a receiver of type `Pointer` /// where `T` is a compile-time constant type. external T operator [](int index); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array. @Since('3.8') external List get elements; } /// Bounds checking indexing methods on [Array]s of [Array]. @Since('2.13') extension ArrayArray on Array> { external Array operator [](int index); external void operator []=(int index, Array value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external List> get elements; } /// Bounds checking indexing methods on [Array]s of [AbiSpecificInteger]. @Since('2.16') extension AbiSpecificIntegerArray on Array { /// Loads a Dart value from this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external int operator [](int index); /// Stores a Dart value in this array at [index]. /// /// This extension method must be invoked on a receiver of type `Array` /// where `T` is a compile-time constant type. external void operator []=(int index, int value); /// A list view of the bytes of this array. /// /// Has the same length and elements (as accessed using the index operator) /// as this array, and writes to either the list or this arrary are visible /// in both. @Since('3.8') external List get elements; } @Since('3.5') extension ArrayAddress on Array { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` can /// only occurr as an entire argument expression in the invocation of a leaf /// [Native] external function. /// /// Example: /// /// ```dart /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// final class MyStruct extends Struct { /// @Array(10) /// external Array array; /// } /// /// void main() { /// final array = Struct.create().array; /// myFunction(array.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension StructAddress on T { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` can /// only occurr as an entire argument expression in the invocation of a leaf /// [Native] external function. /// /// Example: /// /// ```dart /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// final class MyStruct extends Struct { /// @Int8() /// external int x; /// } /// /// void main() { /// final myStruct = Struct.create(); /// myFunction(myStruct.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension UnionAddress on T { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` can /// only occurr as an entire argument expression in the invocation of a leaf /// [Native] external function. /// /// Example: /// /// ```dart /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// final class MyUnion extends Union { /// @Int8() /// external int x; /// } /// /// void main() { /// final myUnion = Union.create(); /// myFunction(myUnion.address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension IntAddress on int { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` can /// only occurr as an entire argument expression in the invocation of a leaf /// [Native] external function. /// /// Can only be used on fields of [Struct] subtypes, fields of [Union] /// subtypes, [Array] elements, or [TypedData] elements. In other words, the /// number whose address is being accessed must itself be acccessed through a /// [Struct], [Union], [Array], or [TypedData]. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// final class MyStruct extends Struct { /// @Int8() /// external int x; /// /// @Int8() /// external int y; /// /// @Array(10) /// external Array array; /// } /// /// void main() { /// final myStruct = Struct.create(); /// myFunction(myStruct.y.address); /// myFunction(myStruct.array[5].address); /// /// final list = Int8List(10); /// myFunction(list[5].address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension DoubleAddress on double { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` can /// only occurr as an entire argument expression in the invocation of a leaf /// [Native] external function. /// /// Can only be used on fields of [Struct] subtypes, fields of [Union] /// subtypes, [Array] elements, or [TypedData] elements. In other words, the /// number whose address is being accessed must itself be acccessed through a /// [Struct], [Union], [Array], or [TypedData]. /// /// Example: /// /// ```dart import:typed_data /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// final class MyStruct extends Struct { /// @Float() /// external double x; /// /// @Float() /// external double y; /// /// @Array(10) /// external Array array; /// } /// /// void main() { /// final myStruct = Struct.create(); /// myFunction(myStruct.y.address); /// myFunction(myStruct.array[5].address); /// /// final list = Float32List(10); /// myFunction(list[5].address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } @Since('3.5') extension BoolAddress on bool { /// The memory address of the underlying data. /// /// An expression of the form `expression.address` denoting this `address` can /// only occurr as an entire argument expression in the invocation of a leaf /// [Native] external function. /// /// Can only be used on fields of [Struct] subtypes, fields of [Union] /// subtypes, or [Array] elements. In other words, the boolean whose address /// is being accessed must itself be acccessed through a [Struct], [Union] or /// [Array]. /// /// Example: /// /// ```dart /// @Native)>(isLeaf: true) /// external void myFunction(Pointer pointer); /// /// final class MyStruct extends Struct { /// @Bool() /// external bool x; /// /// @Bool() /// external bool y; /// /// @Array(10) /// external Array array; /// } /// /// void main() { /// final myStruct = Struct.create(); /// myFunction(myStruct.y.address); /// myFunction(myStruct.array[5].address); /// } /// ``` /// /// The expression before `.address` is evaluated like the left-hand-side of /// an assignment, to something that gives access to the storage behind the /// expression, which can be used both for reading and writing. The `.address` /// then gives a native pointer to that storage. /// /// The `.address` is evaluated just before calling into native code when /// invoking a leaf [Native] external function. This ensures the Dart garbage /// collector will not move the object that the address points in to. external Pointer get address; } /// Extension to retrieve the native `Dart_Port` from a [SendPort]. extension NativePort on SendPort { /// The native port of this [SendPort]. /// /// The returned native port can for example be used by C code to post /// messages to the connected [ReceivePort] via `Dart_PostCObject()` - see /// `dart_native_api.h`. /// /// Only the send ports from the platform classes [ReceivePort] and /// [RawReceivePort] are supported. User-defined implementations of /// [SendPort] are not supported. external int get nativePort; } /// Opaque, not exposing it's members. final class Dart_CObject extends Opaque {} typedef Dart_NativeMessageHandler = Void Function(Int64, Pointer); /// Utilities for accessing the Dart VM API from Dart code or /// from C code via `dart_api_dl.h`. abstract final class NativeApi { /// On breaking changes the major version is increased. /// /// The versioning covers the API surface in `dart_api_dl.h`. external static int get majorVersion; /// On backwards compatible changes the minor version is increased. /// /// The versioning covers the API surface in `dart_api_dl.h`. external static int get minorVersion; /// A function pointer to /// `bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message)` /// in `dart_native_api.h`. external static Pointer< NativeFunction)> > get postCObject; /// A function pointer to /// ```c /// Dart_Port Dart_NewNativePort(const char* name, /// Dart_NativeMessageHandler handler, /// bool handle_concurrently) /// ``` /// in `dart_native_api.h`. external static Pointer< NativeFunction< Int64 Function( Pointer, Pointer>, Int8, ) > > get newNativePort; /// A function pointer to /// `bool Dart_CloseNativePort(Dart_Port native_port_id)` /// in `dart_native_api.h`. external static Pointer> get closeNativePort; /// Pass this to `Dart_InitializeApiDL` in your native code to enable using the /// symbols in `dart_api_dl.h`. external static Pointer get initializeApiDLData; } /// Annotation binding an external declaration to its native implementation. /// /// Can only be applied to `external` declarations of static and top-level /// functions and variables. /// /// A [Native]-annotated `external` function is implemented by native code. /// The implementation is found in the native library denoted by [assetId]. /// Similarly, a [Native]-annotated `external` variable is implemented by /// reading from or writing to native memory. /// /// The compiler and/or runtime provides a binding from [assetId] to native /// library, which depends on the target platform. /// The compiler/runtime can then resolve/lookup symbols (identifiers) /// against the native library, to find a native function or a native global /// variable, and bind an `external` Dart function or variable declaration to /// that native declaration. /// By default, the runtime expects a native symbol with the same name as the /// annotated function or variable in Dart. This can be overridden with the /// [symbol] parameter on the annotation. /// /// When used on a function, [T] must be a function type that represents the /// native function's parameter and return types. The parameter and return types /// must be subtypes of [NativeType]. /// /// When used on a variable, [T] must be a compatible native type. For example, /// an [int] field can be annotated with [Int32]. /// /// If the type argument [T] is omitted in the `@Native` annotation, it is /// inferred from the static type of the declaration, which must meet the /// following constraints: /// /// For function or method declarations: /// - The return type must be one of the following: /// - [Pointer] /// - `void` /// - Subtype of compound types, such as [Struct] or [Union] /// - The parameter types must be subtypes of compound types or [Pointer] /// /// For variable declarations, the type can be any of the following: /// - [Pointer] /// - Subtype of compound types, such as [Struct] or [Union] /// /// For native global variables that cannot be reassigned, a `final` variable in /// Dart or a getter can be used to prevent modifications to the native field. /// /// Example: /// /// ```dart template:top /// @Native() /// external int sum(int a, int b); /// /// @Native() /// external void free(Pointer p); /// /// @Native() /// external int aGlobalInt; /// /// @Native() /// external final Pointer aGlobalString; /// ``` /// /// Calling a `@Native` function, as well as reading or writing to a `@Native` /// variable, will try to resolve the [symbol] in (in the order): /// 1. the provided or default [assetId], /// 2. the native resolver set with `Dart_SetFfiNativeResolver` in /// `dart_api.h`, and /// 3. the current process. /// /// At least one of those three *must* provide a binding for the symbol, /// otherwise the method call or the variable access fails. /// /// NOTE: This is an experimental feature and may change in the future. @Since('2.19') final class Native { // Implementation note: VM hardcodes the layout of this class (number and // order of its fields), so adding/removing/changing fields requires // updating the VM code (see Function::GetNativeAnnotation()). /// The native symbol to be resolved, if not using the default. /// /// If not specified, the default symbol used for native function lookup /// is the annotated function's name. /// /// Example: /// /// ```dart template:top /// @Native() /// external int sum(int a, int b); /// ``` /// /// Example 2: /// /// ```dart template:top /// @Native(symbol: 'sum') /// external int sum(int a, int b); /// ``` /// /// The above two examples are equivalent. /// /// Prefer omitting the [symbol] when possible. final String? symbol; /// The ID of the asset in which [symbol] is resolved, if not using the /// default. /// /// If no asset name is specified, the default is to use an asset ID /// specified using an [DefaultAsset] annotation on the current library's /// `library` declaration, and if there is no [DefaultAsset] annotation on /// the current library, the library's URI (as a string) is used instead. /// /// Example (file `package:a/a.dart`): /// /// ```dart template:top /// @Native() /// external int sum(int a, int b); /// ``` /// /// Example 2 (file `package:a/a.dart`): /// /// ```dart template:none /// @DefaultAsset('package:a/a.dart') /// library a; /// /// import 'dart:ffi'; /// /// @Native() /// external int sum(int a, int b); /// ``` /// /// Example 3 (file `package:a/a.dart`): /// /// ```dart template:top /// @Native(assetId: 'package:a/a.dart') /// external int sum(int a, int b); /// ``` /// /// The above three examples are all equivalent. /// /// Prefer using the library URI as an asset name over specifying it. /// Prefer using an [DefaultAsset] on the `library` declaration /// over specifying the asset name in a [Native] annotation. final String? assetId; /// Whether the function is a leaf function. /// /// Leaf functions are small, short-running, non-blocking functions which are /// not allowed to call back into Dart or use any Dart VM APIs. Leaf functions /// are invoked bypassing some of the heavier parts of the standard /// Dart-to-Native calling sequence which reduces the invocation overhead, /// making leaf calls faster than non-leaf calls. However, this implies that a /// thread executing a leaf function can't cooperate with the Dart runtime. A /// long running or blocking leaf function will delay any operation which /// requires synchronization between all threads associated with an isolate /// group until after the leaf function returns. For example, if one isolate /// in a group is trying to perform a GC and a second isolate is blocked in a /// leaf call, then the first isolate will have to pause and wait until this /// leaf call returns. /// /// This value has no meaning for native fields. final bool isLeaf; const Native({this.assetId, this.isLeaf = false, this.symbol}); /// The native address of the implementation of [native]. /// /// When calling this function, the argument for [native] must be an /// expression denoting a variable or function declaration which is annotated /// with [Native]. /// For a variable declaration, the type [T] must be the same native type /// as the type argument to that `@Native` annotation. /// For a function declaration, the type [T] must be `NativeFunction` /// where `F` was the type argument to that `@Native` annotation. /// /// For example, for a native C library exposing a function: /// /// ```C /// #include /// int64_t sum(int64_t a, int64_t b) { return a + b; } /// ``` /// /// The following code binds `sum` to a Dart function declaration, and /// extracts the address of the native `sum` implementation: /// /// ```dart /// import 'dart:ffi'; /// /// typedef NativeAdd = Int64 Function(Int64, Int64); /// /// @Native() /// external int sum(int a, int b); /// /// void main() { /// Pointer> addressSum = Native.addressOf(sum); /// } /// ``` /// /// Similarly, for a native C library exposing a global variable: /// /// ```C /// const char* myString; /// ``` /// /// The following code binds `myString` to a top-level variable in Dart, and /// extracts the address of the underlying native field: /// /// ```dart /// import 'dart:ffi'; /// /// @Native() /// external Pointer myString; /// /// void main() { /// // This pointer points to the memory location where the loader has /// // placed the `myString` global itself. To get the string value, read /// // the myString field directly. /// Pointer> addressMyString = Native.addressOf(myString); /// } /// ``` @Since('3.3') external static Pointer addressOf( @DartRepresentationOf('T') Object native, ); } /// Annotation specifying the default asset ID for the current library. /// /// The annotation applies only to `library` declarations. /// /// The compiler and/or runtime provides a binding from _asset ID_ to native /// library, which depends on the target platform and architecture. /// The compiler/runtime can resolve identifiers (symbols) /// against the native library, looking up native function implementations /// which are then used as the implementation of `external` Dart function /// declarations. /// /// If used as annotation on a `library` declaration, all [Native]-annotated /// external functions in this library will use the specified asset [id] /// for native function resolution (unless overridden by [Native.assetId]). /// /// If no [DefaultAsset] annotation is provided, the current library's URI /// is the default asset ID for [Native]-annotated external functions. /// /// Example (file `package:a/a.dart`): /// /// ```dart template:top /// @Native() /// external int sum(int a, int b); /// ``` /// /// Example 2 (file `package:a/a.dart`): /// /// ```dart template:none /// @DefaultAsset('package:a/a.dart') /// library a; /// /// import 'dart:ffi'; /// /// @Native() /// external int sum(int a, int b); /// ``` /// /// The above two examples are equivalent. /// /// Prefer using the library URI as asset name when possible. /// /// NOTE: This is an experimental feature and may change in the future. @Since('2.19') final class DefaultAsset { /// The default asset name for [Native] external functions in this library. final String id; const DefaultAsset(this.id); }