[vm/ffi] Pointer load and store as extension methods
Issue: https://github.com/dart-lang/sdk/issues/37773 Change-Id: I836d6305b613cf05590d872874f4517831be3e08 Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-dartkb-linux-debug-simarm64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-dartkb-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-mac-debug-simdbc64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-reload-mac-release-simdbc64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-precomp-mac-release-simarm_x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118992 Reviewed-by: Samir Jindel <sjindel@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
17388522ea
commit
597cd06aec
@@ -364,6 +364,10 @@ class _FfiUseSiteTransformer extends FfiTransformer {
|
||||
// this rewiring.
|
||||
final DartType pointerType = node.receiver.getStaticType(env);
|
||||
final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
|
||||
if (nativeType is TypeParameterType) {
|
||||
// Do not rewire generic invocations.
|
||||
return node;
|
||||
}
|
||||
final Class nativeClass = (nativeType as InterfaceType).classNode;
|
||||
final NativeType nt = getType(nativeClass);
|
||||
if (optimizedTypes.contains(nt)) {
|
||||
|
||||
+2
-18
@@ -50,15 +50,6 @@ static void CheckSized(const AbstractType& type_arg) {
|
||||
|
||||
// The following functions are runtime checks on arguments.
|
||||
|
||||
static const Pointer& AsPointer(const Instance& instance) {
|
||||
if (!instance.IsPointer()) {
|
||||
const String& error = String::Handle(String::NewFormatted(
|
||||
"Expected a Pointer object but found %s", instance.ToCString()));
|
||||
Exceptions::ThrowArgumentError(error);
|
||||
}
|
||||
return Pointer::Cast(instance);
|
||||
}
|
||||
|
||||
static const Integer& AsInteger(const Instance& instance) {
|
||||
if (!instance.IsInteger()) {
|
||||
const String& error = String::Handle(String::NewFormatted(
|
||||
@@ -294,16 +285,10 @@ CLASS_LIST_FFI_NUMERIC(DEFINE_NATIVE_ENTRY_STORE)
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Ffi_storePointer, 0, 2) {
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
|
||||
GET_NATIVE_ARGUMENT(Instance, new_value, arguments->NativeArgAt(1));
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Pointer, new_value, arguments->NativeArgAt(1));
|
||||
AbstractType& pointer_type_arg =
|
||||
AbstractType::Handle(pointer.type_argument());
|
||||
|
||||
if (new_value.IsNull()) {
|
||||
const String& error = String::Handle(
|
||||
String::NewFormatted("Argument to Pointer.store is null."));
|
||||
Exceptions::ThrowArgumentError(error);
|
||||
}
|
||||
|
||||
auto& new_value_type =
|
||||
AbstractType::Handle(zone, new_value.GetType(Heap::kNew));
|
||||
if (!new_value_type.IsSubtypeOf(pointer_type_arg, Heap::kNew)) {
|
||||
@@ -315,9 +300,8 @@ DEFINE_NATIVE_ENTRY(Ffi_storePointer, 0, 2) {
|
||||
}
|
||||
|
||||
ASSERT(IsPointerType(pointer_type_arg));
|
||||
ASSERT(new_value.IsPointer());
|
||||
uword* slot = reinterpret_cast<uword*>(pointer.NativeAddress());
|
||||
*slot = AsPointer(new_value).NativeAddress();
|
||||
*slot = new_value.NativeAddress();
|
||||
return Object::null();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// This file generates the extension methods public API and the extension
|
||||
// methods patch file for all integers, double, and float.
|
||||
// The PointerPointer and PointerStruct extension are written by hand since
|
||||
// those are not repetitive.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
//
|
||||
// Configuration.
|
||||
//
|
||||
|
||||
const Map<String, String> nativeToDartType = {
|
||||
"Int8": "int",
|
||||
"Int16": "int",
|
||||
"Int32": "int",
|
||||
"Int64": "int",
|
||||
"Uint8": "int",
|
||||
"Uint16": "int",
|
||||
"Uint32": "int",
|
||||
"Uint64": "int",
|
||||
"IntPtr": "int",
|
||||
"Float": "double",
|
||||
"Double": "double",
|
||||
};
|
||||
|
||||
//
|
||||
// Generator.
|
||||
//
|
||||
|
||||
main(List<String> arguments) {
|
||||
final parsedArgs = parseArguments(arguments);
|
||||
|
||||
generate(parsedArgs.path, "ffi.g.dart", generatePublicExtension);
|
||||
generate(parsedArgs.path, "ffi_patch.g.dart", generatePatchExtension);
|
||||
}
|
||||
|
||||
void generate(Uri path, String fileName,
|
||||
Function(StringBuffer, String, String) generator) {
|
||||
final buffer = StringBuffer();
|
||||
generateHeader(buffer);
|
||||
nativeToDartType.forEach((String nativeType, String dartType) {
|
||||
generator(buffer, nativeType, dartType);
|
||||
});
|
||||
generateFooter(buffer);
|
||||
|
||||
final fullPath = path.resolve(fileName).path;
|
||||
new File(fullPath).writeAsStringSync(buffer.toString());
|
||||
final fmtResult = Process.runSync(dartfmtPath().path, ["-w", fullPath]);
|
||||
if (fmtResult.exitCode != 0) {
|
||||
throw Exception(
|
||||
"Formatting failed:\n${fmtResult.stdout}\n${fmtResult.stderr}\n");
|
||||
}
|
||||
print("Generated $fullPath.");
|
||||
}
|
||||
|
||||
void generateHeader(StringBuffer buffer) {
|
||||
final header = """
|
||||
//
|
||||
// The following code is generated, do not edit by hand.
|
||||
//
|
||||
// Code generated by `runtime/tools/ffi/sdk_lib_ffi_generator.dart`.
|
||||
//
|
||||
|
||||
""";
|
||||
|
||||
buffer.write(header);
|
||||
}
|
||||
|
||||
void generatePublicExtension(
|
||||
StringBuffer buffer, String nativeType, String dartType) {
|
||||
final storeTrunctateInt = """
|
||||
/// Note that ints which do not fit in [$nativeType] are truncated.
|
||||
""";
|
||||
|
||||
final storeTrunctateDouble = """
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
""";
|
||||
|
||||
final storeTruncate =
|
||||
isInt(nativeType) ? storeTrunctateInt : storeTrunctateDouble;
|
||||
|
||||
final loadSignExtendInt = """
|
||||
/// Note that ints are signextended.
|
||||
""";
|
||||
|
||||
final loadSignExtend = isInt(nativeType) ? loadSignExtendInt : "";
|
||||
|
||||
buffer.write("""
|
||||
/// Extension on [Pointer] specialized for the type argument [$nativeType].
|
||||
extension ${nativeType}Pointer on Pointer<$nativeType> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
$loadSignExtend ///
|
||||
/// Note that [address] needs to be aligned to the size of [$nativeType].
|
||||
external $dartType get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
$storeTruncate ///
|
||||
/// Note that [address] needs to be aligned to the size of [$nativeType].
|
||||
external void set value($dartType value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
$loadSignExtend ///
|
||||
/// Note that [address] needs to be aligned to the size of [$nativeType].
|
||||
external $dartType operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
$storeTruncate ///
|
||||
/// Note that [address] needs to be aligned to the size of [$nativeType].
|
||||
external void operator []=(int index, $dartType value);
|
||||
}
|
||||
|
||||
""");
|
||||
}
|
||||
|
||||
void generatePatchExtension(
|
||||
StringBuffer buffer, String nativeType, String dartType) {
|
||||
buffer.write("""
|
||||
extension ${nativeType}Pointer on Pointer<$nativeType> {
|
||||
@patch
|
||||
$dartType get value => _load$nativeType(this);
|
||||
|
||||
@patch
|
||||
void set value($dartType value) => _store$nativeType(this, value);
|
||||
|
||||
@patch
|
||||
$dartType operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, $dartType value) => this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
""");
|
||||
}
|
||||
|
||||
void generateFooter(StringBuffer buffer) {
|
||||
final footer = """
|
||||
//
|
||||
// End of generated code.
|
||||
//
|
||||
""";
|
||||
|
||||
buffer.write(footer);
|
||||
}
|
||||
|
||||
//
|
||||
// Helper functions.
|
||||
//
|
||||
|
||||
bool isInt(String type) => type.startsWith("Int") || type.startsWith("Uint");
|
||||
|
||||
class Arguments {
|
||||
final Uri path;
|
||||
Arguments(this.path);
|
||||
}
|
||||
|
||||
Arguments parseArguments(List<String> arguments) {
|
||||
final parsedArgs = Map<String, dynamic>();
|
||||
String flag = null;
|
||||
for (final String arg in arguments) {
|
||||
if (flag == "path") {
|
||||
parsedArgs[flag] = Uri.parse(arg);
|
||||
flag = null;
|
||||
} else if (arg == "-p" || arg == "--path") {
|
||||
flag = "path";
|
||||
} else {
|
||||
throw Exception("Unknown argument: $arg");
|
||||
}
|
||||
}
|
||||
|
||||
Uri path = parsedArgs["path"];
|
||||
if (path == null) {
|
||||
path = Platform.script;
|
||||
print("No path provided, generating files next to generator.");
|
||||
}
|
||||
|
||||
return Arguments(path);
|
||||
}
|
||||
|
||||
Uri dartfmtPath() {
|
||||
// TODO(dacoharkes): Use "../../../tools/sdks/dart-sdk/bin/dartfmt" when the
|
||||
// pinned fully supports extension methods.
|
||||
return Uri.parse("dartfmt");
|
||||
}
|
||||
@@ -1074,6 +1074,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
|
||||
|
||||
ASSERT(function.NumParameters() == 1);
|
||||
body += LoadLocal(parsed_function_->RawParameterVariable(0)); // Pointer.
|
||||
body += CheckNullOptimized(TokenPosition::kNoSource,
|
||||
String::ZoneHandle(Z, function.name()));
|
||||
body += LoadNativeField(Slot::Pointer_c_memory_address());
|
||||
body += UnboxTruncate(kUnboxedIntPtr); // Truncating, so signed is ok.
|
||||
body += ConvertIntptrToUntagged(); // Requires signed intptr.
|
||||
@@ -1169,6 +1171,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
|
||||
// But we type check it as a method on a generic class at runtime.
|
||||
body += LoadLocal(arg_value);
|
||||
body += LoadLocal(arg_pointer);
|
||||
body += CheckNullOptimized(TokenPosition::kNoSource,
|
||||
String::ZoneHandle(Z, function.name()));
|
||||
// We pass the Pointer type argument as instantiator_type_args.
|
||||
//
|
||||
// Call sites to this recognized method are guaranteed to pass a
|
||||
@@ -1189,6 +1193,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
|
||||
|
||||
ASSERT(function.NumParameters() == 2);
|
||||
body += LoadLocal(arg_pointer); // Pointer.
|
||||
body += CheckNullOptimized(TokenPosition::kNoSource,
|
||||
String::ZoneHandle(Z, function.name()));
|
||||
body += LoadNativeField(Slot::Pointer_c_memory_address());
|
||||
body += UnboxTruncate(kUnboxedIntPtr); // Truncating, so signed is ok.
|
||||
body += ConvertIntptrToUntagged(); // Requires signed intptr.
|
||||
|
||||
@@ -21494,7 +21494,6 @@ RawDynamicLibrary* DynamicLibrary::New(void* handle, Heap::Space space) {
|
||||
}
|
||||
|
||||
bool Pointer::IsPointer(const Instance& obj) {
|
||||
ASSERT(!obj.IsNull());
|
||||
return RawObject::IsFfiPointerClassId(obj.raw()->GetClassId());
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,8 @@ int _abi()
|
||||
// allocating a Pointer with in elementAt/offsetBy. Allocating these pointers
|
||||
// and GCing new spaces takes a lot of the benchmark time. The next speedup is
|
||||
// getting rid of these allocations by inlining these functions.
|
||||
//
|
||||
// TODO(37773): Change _loadInt8 etc to take an index.
|
||||
int _loadInt8(Pointer<Int8> pointer) native "Ffi_loadInt8";
|
||||
|
||||
int _loadInt16(Pointer<Int16> pointer) native "Ffi_loadInt16";
|
||||
@@ -236,3 +238,204 @@ Pointer<Double> _elementAtDouble(Pointer<Double> pointer, int index) =>
|
||||
Pointer<Pointer<S>> _elementAtPointer<S extends NativeType>(
|
||||
Pointer<Pointer<S>> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + _intPtrSize * index);
|
||||
|
||||
//
|
||||
// The following code is generated, do not edit by hand.
|
||||
//
|
||||
// Code generated by `runtime/tools/ffi/sdk_lib_ffi_generator.dart`.
|
||||
//
|
||||
|
||||
extension Int8Pointer on Pointer<Int8> {
|
||||
@patch
|
||||
int get value => _loadInt8(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt8(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Int16Pointer on Pointer<Int16> {
|
||||
@patch
|
||||
int get value => _loadInt16(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt16(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Int32Pointer on Pointer<Int32> {
|
||||
@patch
|
||||
int get value => _loadInt32(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt32(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Int64Pointer on Pointer<Int64> {
|
||||
@patch
|
||||
int get value => _loadInt64(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt64(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint8Pointer on Pointer<Uint8> {
|
||||
@patch
|
||||
int get value => _loadUint8(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint8(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint16Pointer on Pointer<Uint16> {
|
||||
@patch
|
||||
int get value => _loadUint16(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint16(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint32Pointer on Pointer<Uint32> {
|
||||
@patch
|
||||
int get value => _loadUint32(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint32(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint64Pointer on Pointer<Uint64> {
|
||||
@patch
|
||||
int get value => _loadUint64(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint64(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension IntPtrPointer on Pointer<IntPtr> {
|
||||
@patch
|
||||
int get value => _loadIntPtr(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeIntPtr(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension FloatPointer on Pointer<Float> {
|
||||
@patch
|
||||
double get value => _loadFloat(this);
|
||||
|
||||
@patch
|
||||
void set value(double value) => _storeFloat(this, value);
|
||||
|
||||
@patch
|
||||
double operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, double value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension DoublePointer on Pointer<Double> {
|
||||
@patch
|
||||
double get value => _loadDouble(this);
|
||||
|
||||
@patch
|
||||
void set value(double value) => _storeDouble(this, value);
|
||||
|
||||
@patch
|
||||
double operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, double value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
//
|
||||
// End of generated code.
|
||||
//
|
||||
|
||||
extension PointerPointer<T extends NativeType> on Pointer<Pointer<T>> {
|
||||
@patch
|
||||
Pointer<T> get value => _loadPointer(this);
|
||||
|
||||
@patch
|
||||
void set value(Pointer<T> value) => _storePointer(this, value);
|
||||
|
||||
@patch
|
||||
Pointer<T> operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, Pointer<T> value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension StructPointer<T extends Struct> on Pointer<T> {
|
||||
@patch
|
||||
T get ref => _loadStruct(this);
|
||||
|
||||
@patch
|
||||
T operator [](int index) {
|
||||
Pointer<T> offsetPointer = this.elementAt(index);
|
||||
return offsetPointer.ref;
|
||||
}
|
||||
}
|
||||
|
||||
+442
-3
@@ -63,11 +63,14 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// 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.
|
||||
///
|
||||
/// Note that `address` needs to be aligned to the size of `T`.
|
||||
/// Note that `this.address` needs to be aligned to the size of `T`.
|
||||
///
|
||||
/// Deprecated, use `pointer[...] =` and `pointer.value =` instead.
|
||||
@deprecated
|
||||
external void store(@DartRepresentationOf("T") Object value);
|
||||
|
||||
/// Load a Dart value from this location.
|
||||
@@ -76,7 +79,10 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||
/// Loading a [Struct] reference returns a reference backed by native memory
|
||||
/// (the same pointer as it's loaded from).
|
||||
///
|
||||
/// Note that `address` needs to be aligned to the size of `T`.
|
||||
/// Note that `this.address` needs to be aligned to the size of `T`.
|
||||
///
|
||||
/// Deprecated, use `pointer[...]` and `pointer.value` instead.
|
||||
@deprecated
|
||||
external R load<@DartRepresentationOf("T") R>();
|
||||
|
||||
/// Access to the raw pointer value.
|
||||
@@ -144,3 +150,436 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||
return address.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The following code is generated, do not edit by hand.
|
||||
//
|
||||
// Code generated by `runtime/tools/ffi/sdk_lib_ffi_generator.dart`.
|
||||
//
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int8].
|
||||
extension Int8Pointer on Pointer<Int8> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int16].
|
||||
extension Int16Pointer on Pointer<Int16> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int32].
|
||||
extension Int32Pointer on Pointer<Int32> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int64].
|
||||
extension Int64Pointer on Pointer<Int64> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint8].
|
||||
extension Uint8Pointer on Pointer<Uint8> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint16].
|
||||
extension Uint16Pointer on Pointer<Uint16> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint32].
|
||||
extension Uint32Pointer on Pointer<Uint32> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint64].
|
||||
extension Uint64Pointer on Pointer<Uint64> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [IntPtr].
|
||||
extension IntPtrPointer on Pointer<IntPtr> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [IntPtr] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [IntPtr] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Float].
|
||||
extension FloatPointer on Pointer<Float> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external double get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external void set value(double value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external double operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external void operator []=(int index, double value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Double].
|
||||
extension DoublePointer on Pointer<Double> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external double get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external void set value(double value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external double operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external void operator []=(int index, double value);
|
||||
}
|
||||
|
||||
//
|
||||
// End of generated code.
|
||||
//
|
||||
|
||||
extension PointerPointer<T extends NativeType> on Pointer<Pointer<T>> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external Pointer<T> get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external void set value(Pointer<T> value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external Pointer<T> operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external void operator []=(int index, Pointer<T> value);
|
||||
}
|
||||
|
||||
extension StructPointer<T extends Struct> on Pointer<T> {
|
||||
/// Create a reference backed by native memory (the same pointer as it's loaded from).
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [T].
|
||||
external T get ref;
|
||||
|
||||
/// Create a reference backed by native memory offset by [index].
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [T].
|
||||
external T operator [](int index);
|
||||
}
|
||||
|
||||
@@ -149,6 +149,8 @@ int _abi()
|
||||
// allocating a Pointer with in elementAt/offsetBy. Allocating these pointers
|
||||
// and GCing new spaces takes a lot of the benchmark time. The next speedup is
|
||||
// getting rid of these allocations by inlining these functions.
|
||||
//
|
||||
// TODO(37773): Change _loadInt8 etc to take an index.
|
||||
int _loadInt8(Pointer<Int8> pointer) native "Ffi_loadInt8";
|
||||
|
||||
int _loadInt16(Pointer<Int16> pointer) native "Ffi_loadInt16";
|
||||
@@ -238,3 +240,204 @@ Pointer<Double> _elementAtDouble(Pointer<Double> pointer, int index) =>
|
||||
Pointer<Pointer<S>> _elementAtPointer<S extends NativeType>(
|
||||
Pointer<Pointer<S>> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + _intPtrSize * index);
|
||||
|
||||
//
|
||||
// The following code is generated, do not edit by hand.
|
||||
//
|
||||
// Code generated by `runtime/tools/ffi/sdk_lib_ffi_generator.dart`.
|
||||
//
|
||||
|
||||
extension Int8Pointer on Pointer<Int8> {
|
||||
@patch
|
||||
int get value => _loadInt8(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt8(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Int16Pointer on Pointer<Int16> {
|
||||
@patch
|
||||
int get value => _loadInt16(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt16(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Int32Pointer on Pointer<Int32> {
|
||||
@patch
|
||||
int get value => _loadInt32(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt32(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Int64Pointer on Pointer<Int64> {
|
||||
@patch
|
||||
int get value => _loadInt64(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeInt64(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint8Pointer on Pointer<Uint8> {
|
||||
@patch
|
||||
int get value => _loadUint8(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint8(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint16Pointer on Pointer<Uint16> {
|
||||
@patch
|
||||
int get value => _loadUint16(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint16(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint32Pointer on Pointer<Uint32> {
|
||||
@patch
|
||||
int get value => _loadUint32(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint32(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension Uint64Pointer on Pointer<Uint64> {
|
||||
@patch
|
||||
int get value => _loadUint64(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeUint64(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension IntPtrPointer on Pointer<IntPtr> {
|
||||
@patch
|
||||
int get value => _loadIntPtr(this);
|
||||
|
||||
@patch
|
||||
void set value(int value) => _storeIntPtr(this, value);
|
||||
|
||||
@patch
|
||||
int operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension FloatPointer on Pointer<Float> {
|
||||
@patch
|
||||
double get value => _loadFloat(this);
|
||||
|
||||
@patch
|
||||
void set value(double value) => _storeFloat(this, value);
|
||||
|
||||
@patch
|
||||
double operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, double value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension DoublePointer on Pointer<Double> {
|
||||
@patch
|
||||
double get value => _loadDouble(this);
|
||||
|
||||
@patch
|
||||
void set value(double value) => _storeDouble(this, value);
|
||||
|
||||
@patch
|
||||
double operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, double value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
//
|
||||
// End of generated code.
|
||||
//
|
||||
|
||||
extension PointerPointer<T extends NativeType> on Pointer<Pointer<T>> {
|
||||
@patch
|
||||
Pointer<T> get value => _loadPointer(this);
|
||||
|
||||
@patch
|
||||
void set value(Pointer<T> value) => _storePointer(this, value);
|
||||
|
||||
@patch
|
||||
Pointer<T> operator [](int index) => this.elementAt(index).value;
|
||||
|
||||
@patch
|
||||
void operator []=(int index, Pointer<T> value) =>
|
||||
this.elementAt(index).value = value;
|
||||
}
|
||||
|
||||
extension StructPointer<T extends Struct> on Pointer<T> {
|
||||
@patch
|
||||
T get ref => _loadStruct(this);
|
||||
|
||||
@patch
|
||||
T operator [](int index) {
|
||||
Pointer<T> offsetPointer = this.elementAt(index);
|
||||
return offsetPointer.ref;
|
||||
}
|
||||
}
|
||||
|
||||
+442
-3
@@ -65,11 +65,14 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// 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.
|
||||
///
|
||||
/// Note that `address` needs to be aligned to the size of `T`.
|
||||
/// Note that `this.address` needs to be aligned to the size of `T`.
|
||||
///
|
||||
/// Deprecated, use `pointer[...] =` and `pointer.value =` instead.
|
||||
@deprecated
|
||||
external void store(@DartRepresentationOf("T") Object value);
|
||||
|
||||
/// Load a Dart value from this location.
|
||||
@@ -78,7 +81,10 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||
/// Loading a [Struct] reference returns a reference backed by native memory
|
||||
/// (the same pointer as it's loaded from).
|
||||
///
|
||||
/// Note that `address` needs to be aligned to the size of `T`.
|
||||
/// Note that `this.address` needs to be aligned to the size of `T`.
|
||||
///
|
||||
/// Deprecated, use `pointer[...]` and `pointer.value` instead.
|
||||
@deprecated
|
||||
external R load<@DartRepresentationOf("T") R>();
|
||||
|
||||
/// Access to the raw pointer value.
|
||||
@@ -146,3 +152,436 @@ class Pointer<T extends NativeType> extends NativeType {
|
||||
return address.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The following code is generated, do not edit by hand.
|
||||
//
|
||||
// Code generated by `runtime/tools/ffi/sdk_lib_ffi_generator.dart`.
|
||||
//
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int8].
|
||||
extension Int8Pointer on Pointer<Int8> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int8].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int16].
|
||||
extension Int16Pointer on Pointer<Int16> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int16].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int32].
|
||||
extension Int32Pointer on Pointer<Int32> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int32].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Int64].
|
||||
extension Int64Pointer on Pointer<Int64> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Int64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Int64].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint8].
|
||||
extension Uint8Pointer on Pointer<Uint8> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint8] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint8].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint16].
|
||||
extension Uint16Pointer on Pointer<Uint16> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint16] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint16].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint32].
|
||||
extension Uint32Pointer on Pointer<Uint32> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint32] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint32].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Uint64].
|
||||
extension Uint64Pointer on Pointer<Uint64> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [Uint64] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Uint64].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [IntPtr].
|
||||
extension IntPtrPointer on Pointer<IntPtr> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external int get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [IntPtr] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external void set value(int value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
/// Note that ints are signextended.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external int operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that ints which do not fit in [IntPtr] are truncated.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [IntPtr].
|
||||
external void operator []=(int index, int value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Float].
|
||||
extension FloatPointer on Pointer<Float> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external double get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external void set value(double value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external double operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Float].
|
||||
external void operator []=(int index, double value);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Double].
|
||||
extension DoublePointer on Pointer<Double> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external double get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external void set value(double value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external double operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
/// Note that doubles stored into Pointer<[Float]> lose precision.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Double].
|
||||
external void operator []=(int index, double value);
|
||||
}
|
||||
|
||||
//
|
||||
// End of generated code.
|
||||
//
|
||||
|
||||
extension PointerPointer<T extends NativeType> on Pointer<Pointer<T>> {
|
||||
/// Load a Dart value from this location.
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external Pointer<T> get value;
|
||||
|
||||
/// Store a Dart value into this location.
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external void set value(Pointer<T> value);
|
||||
|
||||
/// Load a Dart value from this location offset by [index].
|
||||
///
|
||||
/// The value is automatically unmarshalled from its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external Pointer<T> operator [](int index);
|
||||
|
||||
/// Store a Dart value into this location offset by [index].
|
||||
///
|
||||
/// The [value] is automatically marshalled into its native representation.
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [Pointer].
|
||||
external void operator []=(int index, Pointer<T> value);
|
||||
}
|
||||
|
||||
extension StructPointer<T extends Struct> on Pointer<T> {
|
||||
/// Create a reference backed by native memory (the same pointer as it's loaded from).
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [T].
|
||||
external T get ref;
|
||||
|
||||
/// Create a reference backed by native memory offset by [index].
|
||||
///
|
||||
/// Note that [address] needs to be aligned to the size of [T].
|
||||
external T operator [](int index);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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.
|
||||
|
||||
import 'dart:ffi';
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main(List<String> arguments) {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
testStoreLoad();
|
||||
testNullReceivers();
|
||||
testNullArguments();
|
||||
testReifiedGeneric();
|
||||
}
|
||||
}
|
||||
|
||||
testStoreLoad() {
|
||||
final p = Pointer<Int8>.allocate(count: 2);
|
||||
p.value = 10;
|
||||
Expect.equals(10, p.value);
|
||||
p[1] = 20;
|
||||
Expect.equals(20, p[1]);
|
||||
|
||||
final p1 = Pointer<Double>.allocate(count: 2);
|
||||
p1.value = 10.0;
|
||||
Expect.approxEquals(10.0, p1.value);
|
||||
p1[1] = 20.0;
|
||||
Expect.approxEquals(20.0, p1[1]);
|
||||
p1.free();
|
||||
|
||||
final p2 = Pointer<Pointer<Int8>>.allocate(count: 2);
|
||||
p2.value = p;
|
||||
Expect.equals(p, p2.value);
|
||||
p2[1] = p;
|
||||
Expect.equals(p, p2[1]);
|
||||
p2.free();
|
||||
p.free();
|
||||
|
||||
final p3 = Pointer<Foo>.allocate();
|
||||
Foo foo = p3.ref;
|
||||
foo.a = 1;
|
||||
Expect.equals(1, foo.a);
|
||||
p3.free();
|
||||
}
|
||||
|
||||
/// With extension methods, the receiver position can be null.
|
||||
testNullReceivers() {
|
||||
Pointer<Int8> p = Pointer.allocate();
|
||||
|
||||
Pointer<Int8> p4 = null;
|
||||
Expect.throws(() => Expect.equals(10, p4.value));
|
||||
Expect.throws(() => p4.value = 10);
|
||||
|
||||
Pointer<Pointer<Int8>> p5 = null;
|
||||
Expect.throws(() => Expect.equals(10, p5.value));
|
||||
Expect.throws(() => p5.value = p);
|
||||
|
||||
Pointer<Foo> p6 = null;
|
||||
Expect.throws(() => Expect.equals(10, p6.ref));
|
||||
|
||||
p.free();
|
||||
}
|
||||
|
||||
testNullArguments() {
|
||||
Pointer<Int8> p = Pointer.allocate();
|
||||
Expect.throws(() => p.value = null);
|
||||
p.free();
|
||||
}
|
||||
|
||||
testReifiedGeneric() {
|
||||
final p = Pointer<Pointer<Int8>>.allocate();
|
||||
Pointer<Pointer<NativeType>> p2 = p;
|
||||
Expect.isTrue(p2.value is Pointer<Int8>);
|
||||
p.free();
|
||||
}
|
||||
|
||||
class Foo extends Struct<Foo> {
|
||||
@Int8()
|
||||
int a;
|
||||
}
|
||||
Reference in New Issue
Block a user