blob: eb1bdcde5c8f0f120657f66653fbc03ffe136642 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file
// @dart = 2.5
/**
* Foreign Function Interface for interoperability with the C programming language.
*
* **NOTE**: Dart:FFI is in technical preview. The overall feature is incomplete,
* may contain issues, and breaking API changes are still expected.
*
* For further details, please see: https://dart.dev/server/c-interop
*
* {@category VM}
*/
library dart.ffi;
import 'dart:typed_data' show TypedData;
part "native_type.dart";
part "annotations.dart";
part "dynamic_library.dart";
part "struct.dart";
/// Number of bytes used by native type T.
///
/// Includes padding and alignment of structs.
external int sizeOf<T extends NativeType>();
/// Represents a pointer into the native C memory.
final Pointer<Void> nullptr = Pointer.fromAddress(0);
/// Represents a pointer into the native C memory. Cannot be extended.
@pragma("vm:entry-point")
class Pointer<T extends NativeType> extends NativeType {
/// Allocate [count] elements of type [T] on the native heap via malloc() and
/// return a pointer to the newly allocated memory.
///
/// Note that the memory is uninitialized.
external factory Pointer.allocate({int count: 1});
/// 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.
///
/// 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.
///
/// Does not accept dynamic invocations -- where the type of the receiver is
/// [dynamic].
external static Pointer<NativeFunction<T>> fromFunction<T extends Function>(
@DartRepresentationOf("T") Function f,
[Object exceptionalReturn]);
/// Store a Dart value into this location.
///
/// The [value] is automatically marshalled into its native representation.
/// Note that ints which do not fit in [T] are truncated and sign extended,
/// and doubles stored into Pointer<[Float]> lose precision.
external void store(@DartRepresentationOf("T") Object value);
/// Load a Dart value from this location.
///
/// The value is automatically unmarshalled from its native representation.
/// Loading a [Struct] reference returns a reference backed by native memory
/// (the same pointer as it's loaded from).
external R load<@DartRepresentationOf("T") R>();
/// Access to the raw pointer value.
/// On 32-bit systems, the upper 32-bits of the result are 0.
external int get address;
/// Pointer arithmetic (takes element size into account).
external Pointer<T> elementAt(int index);
/// Pointer arithmetic (byte offset).
// TODO(dacoharkes): remove this?
// https://github.com/dart-lang/sdk/issues/35883
external Pointer<T> offsetBy(int offsetInBytes);
/// Cast Pointer<T> to a Pointer<V>.
external Pointer<U> cast<U extends NativeType>();
/// Convert to Dart function, automatically marshalling the arguments
/// and return value.
///
/// Can only be called on [Pointer]<[NativeFunction]>. Does not accept dynamic
/// invocations -- where the type of the receiver is [dynamic].
external R asFunction<@DartRepresentationOf("T") R extends Function>();
/// Free memory on the C heap pointed to by this pointer with free().
///
/// Note that this zeros out the address.
external void free();
/// Creates an *external* typed data array backed by this pointer.
///
/// The typed data array returned is only valid for as long as the backing
/// [Pointer]. Accessing any element of the type data array after this
/// [Pointer] has been [Pointer.free()]d will cause undefined behavior.
///
/// Since [Pointer]s do not know their length, the size of the typed data is
/// controlled by `count`, in units of the size of the native type for this
/// [Pointer] (similarly to [Pointer.allocate]).
///
/// The kind of TypedData produced depends on the native type:
///
/// Pointer<Int8> -> Int8List
/// Pointer<Uint8> -> Uint8List
/// etc. up to Int64/Uint64
/// Pointer<IntPtr> -> Int32List/Int64List depending on platform word size
/// Pointer<Float> -> Float32List
/// Pointer<Double> -> Float64List
///
/// Creation of a [Uint8ClampedList] is not supported. Creation of a typed
/// data from a [Pointer] to any other native type is not supported.
///
/// The pointer must be aligned to a multiple of the native type's size.
//
// TODO(37773): Use extension methods to articulate more precise return types.
// We should still keep this member though as a generic way to access a
// Pointer of unknown type.
external TypedData asExternalTypedData({int count: 1});
/// Equality for Pointers only depends on their address.
bool operator ==(other) {
if (other == null) return false;
return address == other.address;
}
/// The hash code for a Pointer only depends on its address.
int get hashCode {
return address.hashCode;
}
}