[vm/ffi] Deprecate Pointer.allocate/free.

Fixes https://dart-review.googlesource.com/c/sdk/+/118442.

Also updates untested sample code in samples/ffi.

Change-Id: Id40a7b8fbb35c5d989269646ebb22864cebcfcac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118441
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Samir Jindel
2019-10-10 13:17:43 +00:00
committed by commit-bot@chromium.org
parent 18aed26e83
commit 63d3012e68
38 changed files with 518 additions and 567 deletions
+1
View File
@@ -37,6 +37,7 @@ dartfix:pkg/dartfix/lib
dev_compiler:pkg/dev_compiler/lib
diagnostic:pkg/diagnostic/lib
expect:pkg/expect/lib
ffi:third_party/pkg/ffi/lib
fixnum:third_party/pkg/fixnum/lib
frontend_server:pkg/frontend_server/lib
front_end:pkg/front_end/lib
+3
View File
@@ -85,6 +85,7 @@ vars = {
"dart_style_tag": "1.3.1", # Please see the note above before updating.
"dartdoc_tag" : "v0.28.7",
"ffi_tag": "f46c1f42c6f7f1938f2ff27c573da72d57c47ded",
"fixnum_tag": "0.10.9",
"glob_tag": "1.1.7",
"html_tag" : "0.14.0+1",
@@ -277,6 +278,8 @@ deps = {
Var("dart_git") + "dart2js_info.git" + "@" + Var("dart2js_info_tag"),
Var("dart_root") + "/third_party/pkg/dartdoc":
Var("dart_git") + "dartdoc.git" + "@" + Var("dartdoc_tag"),
Var("dart_root") + "/third_party/pkg/ffi":
Var("dart_git") + "ffi.git" + "@" + Var("ffi_tag"),
Var("dart_root") + "/third_party/pkg/fixnum":
Var("dart_git") + "fixnum.git" + "@" + Var("fixnum_tag"),
Var("dart_root") + "/third_party/pkg/glob":
@@ -9,6 +9,7 @@ import 'dart:ffi';
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:ffi/ffi.dart';
import 'digest.dart';
import 'types.dart';
@@ -47,12 +48,11 @@ String hash(Pointer<Data> data, int length, Pointer<EVP_MD> hashAlgorithm) {
EVP_DigestInit(context, hashAlgorithm);
EVP_DigestUpdate(context, data, length);
final int resultSize = EVP_MD_CTX_size(context);
final Pointer<Bytes> result =
Pointer<Uint8>.allocate(count: resultSize).cast();
final Pointer<Bytes> result = allocate<Uint8>(count: resultSize).cast();
EVP_DigestFinal(context, result, nullptr.cast());
EVP_MD_CTX_free(context);
final String hash = base64Encode(toUint8List(result.ref, resultSize));
result.free();
free(result);
return hash;
}
@@ -85,13 +85,13 @@ class DigestCMemory extends BenchmarkBase {
Pointer<Data> data; // Data in C memory that we want to digest.
void setup() {
data = Pointer<Uint8>.allocate(count: L).cast();
data = allocate<Uint8>(count: L).cast();
copyFromUint8ListToTarget(inventData(L), data.ref);
hash(data, L, hashAlgorithm);
}
void teardown() {
data.free();
free(data);
}
void run() {
@@ -112,19 +112,19 @@ class DigestDartMemory extends BenchmarkBase {
void setup() {
data = inventData(L);
final Pointer<Data> dataInC = Pointer<Uint8>.allocate(count: L).cast();
final Pointer<Data> dataInC = allocate<Uint8>(count: L).cast();
copyFromUint8ListToTarget(data, dataInC.ref);
hash(dataInC, L, hashAlgorithm);
dataInC.free();
free(dataInC);
}
void teardown() {}
void run() {
final Pointer<Data> dataInC = Pointer<Uint8>.allocate(count: L).cast();
final Pointer<Data> dataInC = allocate<Uint8>(count: L).cast();
copyFromUint8ListToTarget(data, dataInC.ref);
final String result = hash(dataInC, L, hashAlgorithm);
dataInC.free();
free(dataInC);
if (result != expectedHash) {
throw Exception("$name: Unexpected result: $result");
}
+11 -10
View File
@@ -10,6 +10,7 @@
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'dlopen_helper.dart';
@@ -919,8 +920,8 @@ class PointerUint8x01 extends BenchmarkBase {
PointerUint8x01() : super("FfiCall.PointerUint8x01");
Pointer<Uint8> pointer;
void setup() => pointer = Pointer.allocate(count: N + 1);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N + 1);
void teardown() => free(pointer);
void run() {
final Pointer<Uint8> x = doCall1PointerUint8(N, pointer);
@@ -936,12 +937,12 @@ class PointerUint8x02 extends BenchmarkBase {
Pointer<Uint8> pointer, pointer2;
void setup() {
pointer = Pointer.allocate(count: N + 1);
pointer = allocate(count: N + 1);
pointer2 = pointer.elementAt(1);
}
void teardown() {
pointer.free();
free(pointer);
}
void run() {
@@ -958,14 +959,14 @@ class PointerUint8x04 extends BenchmarkBase {
Pointer<Uint8> pointer, pointer2, pointer3, pointer4;
void setup() {
pointer = Pointer.allocate(count: N + 1);
pointer = allocate(count: N + 1);
pointer2 = pointer.elementAt(1);
pointer3 = pointer.elementAt(2);
pointer4 = pointer.elementAt(3);
}
void teardown() {
pointer.free();
free(pointer);
}
void run() {
@@ -992,7 +993,7 @@ class PointerUint8x10 extends BenchmarkBase {
pointer10;
void setup() {
pointer = Pointer.allocate(count: N + 1);
pointer = allocate(count: N + 1);
pointer2 = pointer.elementAt(1);
pointer3 = pointer.elementAt(2);
pointer4 = pointer.elementAt(3);
@@ -1005,7 +1006,7 @@ class PointerUint8x10 extends BenchmarkBase {
}
void teardown() {
pointer.free();
free(pointer);
}
void run() {
@@ -1052,7 +1053,7 @@ class PointerUint8x20 extends BenchmarkBase {
pointer20;
void setup() {
pointer = Pointer.allocate(count: N + 1);
pointer = allocate(count: N + 1);
pointer2 = pointer.elementAt(1);
pointer3 = pointer.elementAt(2);
pointer4 = pointer.elementAt(3);
@@ -1075,7 +1076,7 @@ class PointerUint8x20 extends BenchmarkBase {
}
void teardown() {
pointer.free();
free(pointer);
}
void run() {
+27 -26
View File
@@ -11,6 +11,7 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:benchmark_harness/benchmark_harness.dart';
//
@@ -211,8 +212,8 @@ class PointerInt8 extends BenchmarkBase {
Pointer<Int8> pointer;
PointerInt8() : super("FfiMemory.PointerInt8");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreInt8(pointer, N);
@@ -227,8 +228,8 @@ class PointerUint8 extends BenchmarkBase {
Pointer<Uint8> pointer;
PointerUint8() : super("FfiMemory.PointerUint8");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreUint8(pointer, N);
@@ -243,8 +244,8 @@ class PointerInt16 extends BenchmarkBase {
Pointer<Int16> pointer;
PointerInt16() : super("FfiMemory.PointerInt16");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreInt16(pointer, N);
@@ -259,8 +260,8 @@ class PointerUint16 extends BenchmarkBase {
Pointer<Uint16> pointer;
PointerUint16() : super("FfiMemory.PointerUint16");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreUint16(pointer, N);
@@ -275,8 +276,8 @@ class PointerInt32 extends BenchmarkBase {
Pointer<Int32> pointer;
PointerInt32() : super("FfiMemory.PointerInt32");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreInt32(pointer, N);
@@ -291,8 +292,8 @@ class PointerUint32 extends BenchmarkBase {
Pointer<Uint32> pointer;
PointerUint32() : super("FfiMemory.PointerUint32");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreUint32(pointer, N);
@@ -307,8 +308,8 @@ class PointerInt64 extends BenchmarkBase {
Pointer<Int64> pointer;
PointerInt64() : super("FfiMemory.PointerInt64");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreInt64(pointer, N);
@@ -323,8 +324,8 @@ class PointerUint64 extends BenchmarkBase {
Pointer<Uint64> pointer;
PointerUint64() : super("FfiMemory.PointerUint64");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreUint64(pointer, N);
@@ -339,8 +340,8 @@ class PointerFloat extends BenchmarkBase {
Pointer<Float> pointer;
PointerFloat() : super("FfiMemory.PointerFloat");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreFloat(pointer, N);
@@ -355,8 +356,8 @@ class PointerDouble extends BenchmarkBase {
Pointer<Double> pointer;
PointerDouble() : super("FfiMemory.PointerDouble");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreDouble(pointer, N);
@@ -373,13 +374,13 @@ class PointerPointer extends BenchmarkBase {
PointerPointer() : super("FfiMemory.PointerPointer");
void setup() {
pointer = Pointer.allocate(count: N);
data = Pointer.allocate();
pointer = allocate(count: N);
data = allocate();
}
void teardown() {
pointer.free();
data.free();
free(pointer);
free(data);
}
void run() {
@@ -395,8 +396,8 @@ class PointerInt64Mint extends BenchmarkBase {
Pointer<Int64> pointer;
PointerInt64Mint() : super("FfiMemory.PointerInt64Mint");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreInt64Mint(pointer, N);
+3 -2
View File
@@ -9,6 +9,7 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:benchmark_harness/benchmark_harness.dart';
//
@@ -48,8 +49,8 @@ class FieldLoadStore extends BenchmarkBase {
Pointer<VeryLargeStruct> pointer;
FieldLoadStore() : super("FfiStruct.FieldLoadStore");
void setup() => pointer = Pointer.allocate(count: N);
void teardown() => pointer.free();
void setup() => pointer = allocate(count: N);
void teardown() => free(pointer);
void run() {
doStoreInt32(pointer, N);
-1
View File
@@ -312,7 +312,6 @@ DEFINE_NATIVE_ENTRY(Ffi_sizeOf, 1, 0) {
return Integer::New(SizeOf(type_arg));
}
// Static invocations to this method are translated directly in streaming FGB
// and bytecode FGB. However, we can still reach this entrypoint in the bytecode
// interpreter.
+10 -13
View File
@@ -4,37 +4,34 @@
library FfiTest;
import 'dart:ffi' as ffi;
import 'dart:ffi';
import 'package:ffi/ffi.dart' as ffi;
/// Sample struct for dart:ffi library.
@ffi.struct
class Coordinate extends ffi.Pointer<ffi.Void> {
@ffi.Double()
class Coordinate extends Struct<Coordinate> {
@Double()
double x;
@ffi.Double()
@Double()
double y;
@ffi.Pointer()
Coordinate next;
Pointer<Coordinate> next;
// Implementation generated by @ffi.struct annotation.
external static int sizeOf();
Coordinate offsetBy(int offsetInBytes) =>
super.offsetBy(offsetInBytes).cast();
Coordinate elementAt(int index) => offsetBy(sizeOf() * index);
Coordinate elementAt(int index) => addressOf.elementAt(index).ref;
static Coordinate allocate({int count: 1}) =>
ffi.allocate<ffi.Uint8>(count: count * sizeOf()).cast();
ffi.allocate<Coordinate>(count: count).ref;
/// Allocate a new [Coordinate] in C memory and populate its fields.
factory Coordinate(double x, double y, Coordinate next) {
Coordinate result = Coordinate.allocate()
..x = x
..y = y
..next = next;
..next = next.addressOf;
return result;
}
}
+97 -96
View File
@@ -2,75 +2,76 @@
// 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' as ffi;
import 'dart:ffi';
import 'package:ffi/ffi.dart';
main(List<String> arguments) {
print('start main');
{
// basic operation: allocate, get, set, and free
ffi.Pointer<ffi.Int64> p = ffi.allocate();
p.store(42);
int pValue = p.load();
Pointer<Int64> p = allocate();
p.value = 42;
int pValue = p.value;
print('${p.runtimeType} value: ${pValue}');
p.free();
free(p);
}
{
// undefined behavior before set
ffi.Pointer<ffi.Int64> p = ffi.allocate();
int pValue = p.load();
Pointer<Int64> p = allocate();
int pValue = p.value;
print('If not set, returns garbage: ${pValue}');
p.free();
free(p);
}
{
// pointers can be created from an address
ffi.Pointer<ffi.Int64> pHelper = ffi.allocate();
pHelper.store(1337);
Pointer<Int64> pHelper = allocate();
pHelper.value = 1337;
int address = pHelper.address;
print('Address: ${address}');
ffi.Pointer<ffi.Int64> p = ffi.fromAddress(address);
print('${p.runtimeType} value: ${p.load<int>()}');
Pointer<Int64> p = Pointer.fromAddress(address);
print('${p.runtimeType} value: ${p.value}');
pHelper.free();
free(pHelper);
}
{
// address is zeroed out after free
ffi.Pointer<ffi.Int64> p = ffi.allocate();
p.free();
Pointer<Int64> p = allocate();
free(p);
print('After free, address is zero: ${p.address}');
}
{
// pointer arithmetic can be done with element offsets or bytes
ffi.Pointer<ffi.Int64> p1 = ffi.allocate<ffi.Int64>(count: 2);
Pointer<Int64> p1 = allocate<Int64>(count: 2);
print('p1 address: ${p1.address}');
ffi.Pointer<ffi.Int64> p2 = p1.elementAt(1);
Pointer<Int64> p2 = p1.elementAt(1);
print('p1.elementAt(1) address: ${p2.address}');
p2.store(100);
p2.value = 100;
ffi.Pointer<ffi.Int64> p3 = p1.offsetBy(8);
Pointer<Int64> p3 = p1.offsetBy(8);
print('p1.offsetBy(8) address: ${p3.address}');
print('p1.offsetBy(8) value: ${p3.load<int>()}');
p1.free();
print('p1.offsetBy(8) value: ${p3.value}');
free(p1);
}
{
// allocating too much throws an exception
try {
int maxMint = 9223372036854775807; // 2^63 - 1
ffi.allocate<ffi.Int64>(count: maxMint);
allocate<Int64>(count: maxMint);
} on RangeError {
print('Expected exception on allocating too much');
}
try {
int maxInt1_8 = 1152921504606846975; // 2^60 -1
ffi.allocate<ffi.Int64>(count: maxInt1_8);
allocate<Int64>(count: maxInt1_8);
} on ArgumentError {
print('Expected exception on allocating too much');
}
@@ -79,83 +80,83 @@ main(List<String> arguments) {
{
// pointers can be cast into another type
// resulting in the corresponding bits read
ffi.Pointer<ffi.Int64> p1 = ffi.allocate();
p1.store(9223372036854775807); // 2^63 - 1
Pointer<Int64> p1 = allocate();
p1.value = 9223372036854775807; // 2^63 - 1
ffi.Pointer<ffi.Int32> p2 = p1.cast();
print('${p2.runtimeType} value: ${p2.load<int>()}'); // -1
Pointer<Int32> p2 = p1.cast();
print('${p2.runtimeType} value: ${p2.value}'); // -1
ffi.Pointer<ffi.Int32> p3 = p2.elementAt(1);
print('${p3.runtimeType} value: ${p3.load<int>()}'); // 2^31 - 1
Pointer<Int32> p3 = p2.elementAt(1);
print('${p3.runtimeType} value: ${p3.value}'); // 2^31 - 1
p1.free();
free(p1);
}
{
// data can be tightly packed in memory
ffi.Pointer<ffi.Int8> p = ffi.allocate(count: 8);
Pointer<Int8> p = allocate(count: 8);
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
p.elementAt(i).store(i * 3);
p.elementAt(i).value = i * 3;
}
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
print('p.elementAt($i) value: ${p.elementAt(i).load<int>()}');
print('p.elementAt($i) value: ${p.elementAt(i).value}');
}
p.free();
free(p);
}
{
// exception on storing a value that does not fit
ffi.Pointer<ffi.Int32> p11 = ffi.allocate();
Pointer<Int32> p11 = allocate();
try {
p11.store(9223372036854775807);
p11.value = 9223372036854775807;
} on ArgumentError {
print('Expected exception on calling set with a value that does not fit');
}
p11.free();
free(p11);
}
{
// doubles
ffi.Pointer<ffi.Double> p = ffi.allocate();
p.store(3.14159265359);
print('${p.runtimeType} value: ${p.load<double>()}');
p.store(3.14);
print('${p.runtimeType} value: ${p.load<double>()}');
p.free();
Pointer<Double> p = allocate();
p.value = 3.14159265359;
print('${p.runtimeType} value: ${p.value}');
p.value = 3.14;
print('${p.runtimeType} value: ${p.value}');
free(p);
}
{
// floats
ffi.Pointer<ffi.Float> p = ffi.allocate();
p.store(3.14159265359);
print('${p.runtimeType} value: ${p.load<double>()}');
p.store(3.14);
print('${p.runtimeType} value: ${p.load<double>()}');
p.free();
Pointer<Float> p = allocate();
p.value = 3.14159265359;
print('${p.runtimeType} value: ${p.value}');
p.value = 3.14;
print('${p.runtimeType} value: ${p.value}');
free(p);
}
{
// ffi.IntPtr varies in size based on whether the platform is 32 or 64 bit
// IntPtr varies in size based on whether the platform is 32 or 64 bit
// addresses of pointers fit in this size
ffi.Pointer<ffi.IntPtr> p = ffi.allocate();
Pointer<IntPtr> p = allocate();
int p14addr = p.address;
p.store(p14addr);
int pValue = p.load();
p.value = p14addr;
int pValue = p.value;
print('${p.runtimeType} value: ${pValue}');
p.free();
free(p);
}
{
// void pointers are unsized
// the size of the element it is pointing to is undefined
// this means they cannot be ffi.allocated, read, or written
// this means they cannot be allocated, read, or written
// this would would fail to compile:
// ffi.allocate<ffi.Void>();
// allocate<Void>();
ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
ffi.Pointer<ffi.Void> p2 = p1.cast();
Pointer<IntPtr> p1 = allocate();
Pointer<Void> p2 = p1.cast();
print('${p2.runtimeType} address: ${p2.address}');
// this fails to compile, we cannot read something unsized
@@ -164,98 +165,98 @@ main(List<String> arguments) {
// this fails to compile, we cannot write something unsized
// p2.store(1234);
p1.free();
free(p1);
}
{
// pointer to a pointer to something
ffi.Pointer<ffi.Int16> pHelper = ffi.allocate();
pHelper.store(17);
Pointer<Int16> pHelper = allocate();
pHelper.value = 17;
ffi.Pointer<ffi.Pointer<ffi.Int16>> p = ffi.allocate();
Pointer<Pointer<Int16>> p = allocate();
// storing into a pointer pointer automatically unboxes
p.store(pHelper);
p.value = pHelper;
// reading from a pointer pointer automatically boxes
ffi.Pointer<ffi.Int16> pHelper2 = p.load();
print('${pHelper2.runtimeType} value: ${pHelper2.load<int>()}');
Pointer<Int16> pHelper2 = p.value;
print('${pHelper2.runtimeType} value: ${pHelper2.value}');
int pValue = p.load<ffi.Pointer<ffi.Int16>>().load();
int pValue = p.value.value;
print('${p.runtimeType} value\'s value: ${pValue}');
p.free();
pHelper.free();
free(p);
free(pHelper);
}
{
// the pointer to pointer types must match up
ffi.Pointer<ffi.Int8> pHelper = ffi.allocate();
pHelper.store(123);
Pointer<Int8> pHelper = allocate();
pHelper.value = 123;
ffi.Pointer<ffi.Pointer<ffi.Int16>> p = ffi.allocate();
Pointer<Pointer<Int16>> p = allocate();
// this fails to compile due to type mismatch
// p.store(pHelper);
pHelper.free();
p.free();
free(pHelper);
free(p);
}
{
// null pointer in Dart points to address 0 in c++
ffi.Pointer<ffi.Pointer<ffi.Int8>> pointerToPointer = ffi.allocate();
ffi.Pointer<ffi.Int8> value = null;
pointerToPointer.store(value);
value = pointerToPointer.load();
Pointer<Pointer<Int8>> pointerToPointer = allocate();
Pointer<Int8> value = null;
pointerToPointer.value = value;
value = pointerToPointer.value;
print("Loading a pointer to the 0 address is null: ${value}");
pointerToPointer.free();
free(pointerToPointer);
}
{
// sizeof returns element size in bytes
print('sizeOf<ffi.Double>(): ${ffi.sizeOf<ffi.Double>()}');
print('sizeOf<ffi.Int16>(): ${ffi.sizeOf<ffi.Int16>()}');
print('sizeOf<ffi.IntPtr>(): ${ffi.sizeOf<ffi.IntPtr>()}');
print('sizeOf<Double>(): ${sizeOf<Double>()}');
print('sizeOf<Int16>(): ${sizeOf<Int16>()}');
print('sizeOf<IntPtr>(): ${sizeOf<IntPtr>()}');
}
{
// only concrete sub types of NativeType can be ffi.allocated
// only concrete sub types of NativeType can be allocated
// this would fail to compile:
// ffi.allocate();
// allocate();
}
{
// only concrete sub types of NativeType can be asked for size
// this would fail to compile:
// ffi.sizeOf();
// sizeOf();
}
{
// with ffi.IntPtr pointers, one can manually setup aribtrary data
// with IntPtr pointers, one can manually setup aribtrary data
// structres in C memory.
void createChain(ffi.Pointer<ffi.IntPtr> head, int length, int value) {
void createChain(Pointer<IntPtr> head, int length, int value) {
if (length == 0) {
head.store(value);
head.value = value;
return;
}
ffi.Pointer<ffi.IntPtr> next = ffi.allocate<ffi.IntPtr>();
head.store(next.address);
Pointer<IntPtr> next = allocate<IntPtr>();
head.value = next.address;
createChain(next, length - 1, value);
}
int getChainValue(ffi.Pointer<ffi.IntPtr> head, int length) {
int getChainValue(Pointer<IntPtr> head, int length) {
if (length == 0) {
return head.load();
return head.value;
}
ffi.Pointer<ffi.IntPtr> next = ffi.fromAddress(head.load());
Pointer<IntPtr> next = Pointer.fromAddress(head.value);
return getChainValue(next, length - 1);
}
void freeChain(ffi.Pointer<ffi.IntPtr> head, int length) {
ffi.Pointer<ffi.IntPtr> next = ffi.fromAddress(head.load());
head.free();
void freeChain(Pointer<IntPtr> head, int length) {
Pointer<IntPtr> next = Pointer.fromAddress(head.value);
free(head);
if (length == 0) {
return;
}
@@ -263,7 +264,7 @@ main(List<String> arguments) {
}
int length = 10;
ffi.Pointer<ffi.IntPtr> head = ffi.allocate();
Pointer<IntPtr> head = allocate();
createChain(head, length, 512);
int tailValue = getChainValue(head, length);
print('tailValue: ${tailValue}');
+5 -3
View File
@@ -4,6 +4,8 @@
import 'dart:ffi' as ffi;
import 'package:ffi/ffi.dart';
import 'dylib_utils.dart';
typedef NativeUnaryOp = ffi.Int32 Function(ffi.Int32);
@@ -193,7 +195,7 @@ main(List<String> arguments) {
// pass an array / pointer as argument
Int64PointerUnOp assign1337Index1 = ffiTestFunctions
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
ffi.Pointer<ffi.Int64> p2 = allocate(count: 2);
p2.store(42);
p2.elementAt(1).store(1000);
print(p2.elementAt(1).address.toRadixString(16));
@@ -258,11 +260,11 @@ main(List<String> arguments) {
print(result);
print(result.runtimeType);
ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
ffi.Pointer<ffi.Int64> p2 = allocate(count: 2);
result = nullableInt64ElemAt1(p2);
print(result);
print(result.runtimeType);
p2.free();
free(p2);
}
print("end main");
@@ -46,7 +46,7 @@ main(List<String> arguments) {
ffiTestFunctions.lookup("CoordinateUnOpTrice");
CoordinateTrice coordinateUnOpTrice = p2.asFunction();
Coordinate c1 = Coordinate(10.0, 20.0, null);
c1.next = c1;
c1.next = c1.addressOf;
Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1);
print(result.runtimeType);
print(result.x);
@@ -67,7 +67,7 @@ main(List<String> arguments) {
{
ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> pointer =
ffi.fromFunction(myPlus);
ffi.Pointer.fromFunction(myPlus);
print(pointer);
ffi.Pointer<ffi.NativeFunction<NativeApplyTo42And74Type>> p17 =
@@ -24,7 +24,7 @@ main(List<String> arguments) {
Coordinate c1 = Coordinate(10.0, 20.0, null);
Coordinate c2 = Coordinate(42.0, 84.0, c1);
c1.next = c2;
c1.next = c2.addressOf;
Coordinate result = f1(c1);
@@ -48,13 +48,13 @@ main(List<String> arguments) {
Coordinate c3 = c1.elementAt(2);
c1.x = 10.0;
c1.y = 10.0;
c1.next = c3;
c1.next = c3.addressOf;
c2.x = 20.0;
c2.y = 20.0;
c2.next = c1;
c2.next = c1.addressOf;
c3.x = 30.0;
c3.y = 30.0;
c3.next = c2;
c3.next = c2.addressOf;
Coordinate result = f1(c1);
+16 -14
View File
@@ -2,7 +2,9 @@
// 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' as ffi;
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'coordinate.dart';
@@ -14,17 +16,17 @@ main(List<String> arguments) {
Coordinate c1 = Coordinate(10.0, 10.0, null);
Coordinate c2 = Coordinate(20.0, 20.0, c1);
Coordinate c3 = Coordinate(30.0, 30.0, c2);
c1.next = c3;
c1.next = c3.addressOf;
Coordinate currentCoordinate = c1;
for (var i in [0, 1, 2, 3, 4]) {
currentCoordinate = currentCoordinate.next;
currentCoordinate = currentCoordinate.next.ref;
print("${currentCoordinate.x}; ${currentCoordinate.y}");
}
c1.free();
c2.free();
c3.free();
free(c1.addressOf);
free(c2.addressOf);
free(c3.addressOf);
}
{
@@ -34,29 +36,29 @@ main(List<String> arguments) {
Coordinate c3 = c1.elementAt(2);
c1.x = 10.0;
c1.y = 10.0;
c1.next = c3;
c1.next = c3.addressOf;
c2.x = 20.0;
c2.y = 20.0;
c2.next = c1;
c2.next = c1.addressOf;
c3.x = 30.0;
c3.y = 30.0;
c3.next = c2;
c3.next = c2.addressOf;
Coordinate currentCoordinate = c1;
for (var i in [0, 1, 2, 3, 4]) {
currentCoordinate = currentCoordinate.next;
currentCoordinate = currentCoordinate.next.ref;
print("${currentCoordinate.x}; ${currentCoordinate.y}");
}
c1.free();
free(c1.addressOf);
}
{
Coordinate c = Coordinate(10, 10, null);
print(c is Coordinate);
print(c is ffi.Pointer<ffi.Void>);
print(c is ffi.Pointer);
c.free();
print(c is Pointer<Void>);
print(c is Pointer);
free(c.addressOf);
}
print("end main");
-2
View File
@@ -2,8 +2,6 @@
// 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 "package:test/test.dart";
import "../lib/sqlite.dart";
void main() {
@@ -3,8 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
import "dart:ffi";
import "package:ffi/ffi.dart";
import "../ffi/utf8.dart";
import "../ffi/dylib_utils.dart";
import "signatures.dart";
@@ -4,7 +4,7 @@
import "dart:ffi";
import "../ffi/utf8.dart";
import "package:ffi/ffi.dart";
import "types.dart";
@@ -4,8 +4,6 @@
import "dart:ffi";
import "../ffi/utf8.dart";
/// Database Connection Handle
///
/// Each open SQLite database is represented by a pointer to an instance of
+14 -13
View File
@@ -5,6 +5,8 @@
import "dart:collection";
import "dart:ffi";
import "package:ffi/ffi.dart";
import "bindings/bindings.dart";
import "bindings/types.dart" as types;
@@ -12,7 +14,6 @@ import "bindings/types.dart" hide Database;
import "bindings/constants.dart";
import "collections/closable_iterator.dart";
import "ffi/utf8.dart";
/// [Database] represents an open connection to a SQLite database.
///
@@ -26,13 +27,13 @@ class Database {
/// Open a database located at the file [path].
Database(String path,
[int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) {
Pointer<Pointer<types.Database>> dbOut = Pointer.allocate();
final pathC = Utf8.allocate(path);
Pointer<Pointer<types.Database>> dbOut = allocate();
final pathC = Utf8.toUtf8(path);
final int resultCode =
bindings.sqlite3_open_v2(pathC, dbOut, flags, Pointer.fromAddress(0));
_database = dbOut.value;
dbOut.free();
pathC.free();
free(dbOut);
free(pathC);
if (resultCode == Errors.SQLITE_OK) {
_open = true;
@@ -62,13 +63,13 @@ class Database {
/// Execute a query, discarding any returned rows.
void execute(String query) {
Pointer<Pointer<Statement>> statementOut = Pointer.allocate();
Pointer<Utf8> queryC = Utf8.allocate(query);
Pointer<Pointer<Statement>> statementOut = allocate();
Pointer<Utf8> queryC = Utf8.toUtf8(query);
int resultCode = bindings.sqlite3_prepare_v2(
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
Pointer<Statement> statement = statementOut.value;
statementOut.free();
queryC.free();
free(statementOut);
free(queryC);
while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) {
resultCode = bindings.sqlite3_step(statement);
@@ -81,13 +82,13 @@ class Database {
/// Evaluate a query and return the resulting rows as an iterable.
Result query(String query) {
Pointer<Pointer<Statement>> statementOut = Pointer.allocate();
Pointer<Utf8> queryC = Utf8.allocate(query);
Pointer<Pointer<Statement>> statementOut = allocate();
Pointer<Utf8> queryC = Utf8.toUtf8(query);
int resultCode = bindings.sqlite3_prepare_v2(
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
Pointer<Statement> statement = statementOut.value;
statementOut.free();
queryC.free();
free(statementOut);
free(queryC);
if (resultCode != Errors.SQLITE_OK) {
bindings.sqlite3_finalize(statement);
+3 -1
View File
@@ -5,6 +5,8 @@
import "dart:async";
import "dart:ffi";
import 'package:ffi/ffi.dart';
/// [Arena] manages allocated C memory.
///
/// Arenas are zoned.
@@ -22,7 +24,7 @@ class Arena {
/// Frees all memory pointed to by [Pointer]s in this arena.
void finalize() {
for (final ptr in _allocations) {
ptr.free();
free(ptr);
}
}
-48
View File
@@ -1,48 +0,0 @@
// 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:convert";
import "dart:ffi";
import "arena.dart";
/// Represents a String in C memory, managed by an [Arena].
class Utf8 extends Struct<Utf8> {
@Uint8()
int char;
/// Allocates a [CString] in the current [Arena] and populates it with
/// [dartStr].
static Pointer<Utf8> fromString(String dartStr) =>
Utf8.fromStringArena(Arena.current(), dartStr);
/// Allocates a [CString] in [arena] and populates it with [dartStr].
static Pointer<Utf8> fromStringArena(Arena arena, String dartStr) =>
arena.scoped(allocate(dartStr));
/// Allocate a [CString] not managed in and populates it with [dartStr].
///
/// This [CString] is not managed by an [Arena]. Please ensure to [free] the
/// memory manually!
static Pointer<Utf8> allocate(String dartStr) {
List<int> units = Utf8Encoder().convert(dartStr);
Pointer<Utf8> str = Pointer.allocate(count: units.length + 1);
for (int i = 0; i < units.length; ++i) {
str[i].char = units[i];
}
str[units.length].char = 0;
return str.cast();
}
/// Read the string for C memory into Dart.
String toString() {
final str = addressOf;
if (str == nullptr) return null;
int len = 0;
while (str[++len].char != 0);
List<int> units = List(len);
for (int i = 0; i < len; ++i) units[i] = str[i].char;
return Utf8Decoder().convert(units);
}
}
+1 -1
View File
@@ -6,4 +6,4 @@ author: Daco Harkes <dacoharkes@google.com>, Samir Jindel <sjindel@google.com>
environment:
sdk: '>=2.1.0 <3.0.0'
dev_dependencies:
test: ^1.5.3
test: ^1.5.3
+4 -5
View File
@@ -4,12 +4,11 @@
// VMOptions=--optimization-counter-threshold=5
import 'dart:ffi';
import "dart:ffi";
import "package:ffi/ffi.dart";
import "package:test/test.dart";
import '../lib/sqlite.dart';
import '../lib/src/ffi/utf8.dart';
void main() {
test("sqlite integration test", () {
@@ -168,8 +167,8 @@ void main() {
});
test("Utf8 unit test", () {
final String test = 'Hasta Mañana';
final medium = Utf8.allocate(test);
final medium = Utf8.toUtf8(test);
expect(test, medium.ref.toString());
medium.free();
free(medium);
});
}
+15 -1
View File
@@ -36,6 +36,12 @@ class Pointer<T extends NativeType> extends NativeType {
/// return a pointer to the newly allocated memory.
///
/// Note that the memory is uninitialized.
///
/// On Windows, this memory may only be freed via [Pointer.free].
///
/// This method is deprecated. Please resolve allocation methods via
/// [DynamicLibrary] instead, or use "package:ffi".
@deprecated
external factory Pointer.allocate({int count: 1});
/// Construction from raw integer.
@@ -69,7 +75,8 @@ class Pointer<T extends NativeType> extends NativeType {
///
/// Note that `this.address` needs to be aligned to the size of `T`.
///
/// Deprecated, use `pointer[...] =` and `pointer.value =` instead.
/// Deprecated, use `pointer[...] =` and `pointer.value =` instead, or use
/// "package:ffi".
@deprecated
external void store(@DartRepresentationOf("T") Object value);
@@ -108,6 +115,13 @@ class Pointer<T extends NativeType> extends NativeType {
external R asFunction<@DartRepresentationOf("T") R extends Function>();
/// Free memory on the C heap pointed to by this pointer with free().
///
/// On Windows, this method may only be used with a pointer allocated via
/// [Pointer.allocate].
///
/// This method is deprecated. Please resolve allocation methods via
/// [DynamicLibrary] instead.
@deprecated
external void free();
/// Creates an *external* typed data array backed by this pointer.
+13
View File
@@ -38,6 +38,12 @@ class Pointer<T extends NativeType> extends NativeType {
/// return a pointer to the newly allocated memory.
///
/// Note that the memory is uninitialized.
///
/// On Windows, this memory may only be freed via [Pointer.free].
///
/// This method is deprecated. Please resolve allocation methods via
/// [DynamicLibrary] instead.
@deprecated
external factory Pointer.allocate({int count: 1});
/// Construction from raw integer.
@@ -110,6 +116,13 @@ class Pointer<T extends NativeType> extends NativeType {
external R asFunction<@DartRepresentationOf("T") R extends Function>();
/// Free memory on the C heap pointed to by this pointer with free().
///
/// On Windows, this method may only be used with a pointer allocated via
/// [Pointer.allocate].
///
/// This method is deprecated. Please resolve allocation methods via
/// [DynamicLibrary] instead.
@deprecated
external void free();
/// Creates an *external* typed data array backed by this pointer.
+33 -32
View File
@@ -12,6 +12,7 @@ library FfiTest;
import 'dart:ffi';
import "package:ffi/ffi.dart";
import "package:expect/expect.dart";
import 'dylib_utils.dart';
@@ -36,28 +37,28 @@ void main() {
}
void testNonAlias() {
final source = Pointer<Int64>.allocate();
final source = allocate<Int64>();
source.value = 42;
final int a = source.value;
source.value = 1984;
// alias.value should be re-executed, as we wrote to alias.
Expect.notEquals(a, source.value);
source.free();
free(source);
}
void testAliasCast() {
final source = Pointer<Int64>.allocate();
final source = allocate<Int64>();
final alias = source.cast<Int8>().cast<Int64>();
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
free(source);
}
void testAliasCast2() {
final source = Pointer<Int64>.allocate();
final source = allocate<Int64>();
final alias = source.cast<Int16>().cast<Int64>();
final alias2 = source.cast<Int8>().cast<Int64>();
alias.value = 42;
@@ -65,22 +66,22 @@ void testAliasCast2() {
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
free(source);
}
void testAliasOffsetBy() {
final source = Pointer<Int64>.allocate(count: 2);
final source = allocate<Int64>(count: 2);
final alias = source.offsetBy(8).offsetBy(-8);
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
free(source);
}
void testAliasOffsetBy2() {
final source = Pointer<Int64>.allocate(count: 3);
final source = allocate<Int64>(count: 3);
final alias = source.offsetBy(16).offsetBy(-16);
final alias2 = source.offsetBy(8).offsetBy(-8);
alias.value = 42;
@@ -88,22 +89,22 @@ void testAliasOffsetBy2() {
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
free(source);
}
void testAliasElementAt() {
final source = Pointer<Int64>.allocate(count: 2);
final source = allocate<Int64>(count: 2);
final alias = source.elementAt(1).elementAt(-1);
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
free(source);
}
void testAliasElementAt2() {
final source = Pointer<Int64>.allocate(count: 3);
final source = allocate<Int64>(count: 3);
final alias = source.elementAt(2).elementAt(-2);
final alias2 = source.elementAt(1).elementAt(-1);
alias.value = 42;
@@ -111,22 +112,22 @@ void testAliasElementAt2() {
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
free(source);
}
void testAliasFromAddress() {
final source = Pointer<Int64>.allocate();
final source = allocate<Int64>();
final alias = Pointer<Int64>.fromAddress(source.address);
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
free(source);
}
void testAliasFromAddress2() {
final source = Pointer<Int64>.allocate();
final source = allocate<Int64>();
final alias = Pointer<Int64>.fromAddress(source.address);
final alias2 = Pointer<Int64>.fromAddress(source.address);
alias.value = 42;
@@ -134,12 +135,12 @@ void testAliasFromAddress2() {
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
free(source);
}
void testAliasFromAddressViaMemory() {
final helper = Pointer<IntPtr>.allocate();
final source = Pointer<Int64>.allocate();
final helper = allocate<IntPtr>();
final source = allocate<Int64>();
helper.value = source.address;
final alias = Pointer<Int64>.fromAddress(helper.value);
source.value = 42;
@@ -147,13 +148,13 @@ void testAliasFromAddressViaMemory() {
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
helper.free();
source.free();
free(helper);
free(source);
}
void testAliasFromAddressViaMemory2() {
final helper = Pointer<IntPtr>.allocate();
final source = Pointer<Int64>.allocate();
final helper = allocate<IntPtr>();
final source = allocate<Int64>();
helper.value = source.address;
final alias = Pointer<Int64>.fromAddress(helper.value);
final alias2 = Pointer<Int64>.fromAddress(helper.value);
@@ -162,8 +163,8 @@ void testAliasFromAddressViaMemory2() {
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
helper.free();
source.free();
free(helper);
free(source);
}
typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
@@ -175,7 +176,7 @@ QuadOp intComputation = ffiTestFunctions
.lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
void testAliasFromAddressViaNativeFunction() {
final source = Pointer<Int64>.allocate();
final source = allocate<Int64>();
final alias =
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
source.value = 42;
@@ -183,11 +184,11 @@ void testAliasFromAddressViaNativeFunction() {
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
free(source);
}
void testAliasFromAddressViaNativeFunction2() {
final source = Pointer<Int64>.allocate();
final source = allocate<Int64>();
final alias =
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
final alias2 =
@@ -197,7 +198,7 @@ void testAliasFromAddressViaNativeFunction2() {
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
free(source);
}
@pragma('vm:never-inline')
@@ -205,11 +206,11 @@ Pointer<Int8> makeDerived(Pointer<Int64> source) =>
source.offsetBy(7).cast<Int8>();
testPartialOverlap() {
final source = Pointer<Int64>.allocate(count: 2);
final source = allocate<Int64>(count: 2);
final derived = makeDerived(source);
source.value = 0x1122334455667788;
final int value = source.value;
derived.value = 0xaa;
Expect.notEquals(value, source.value);
source.free();
free(source);
}
+2 -1
View File
@@ -5,6 +5,7 @@
library FfiTest;
import 'dart:ffi';
import "package:ffi/ffi.dart";
/// Sample struct for dart:ffi library.
class Coordinate extends Struct<Coordinate> {
@@ -17,7 +18,7 @@ class Coordinate extends Struct<Coordinate> {
Pointer<Coordinate> next;
factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
return Pointer<Coordinate>.allocate().ref
return allocate<Coordinate>().ref
..x = x
..y = y
..next = next;
+4 -3
View File
@@ -11,6 +11,7 @@ library FfiTest;
import 'dart:ffi';
import "package:ffi/ffi.dart";
import "package:expect/expect.dart";
void main() {
@@ -21,16 +22,16 @@ void main() {
void testPointerAllocateTooLarge() {
// Try to allocate something that doesn't fit in 64 bit address space.
int maxInt = 9223372036854775807; // 2^63 - 1
Expect.throws(() => Pointer<Int64>.allocate(count: maxInt));
Expect.throws(() => allocate<Int64>(count: maxInt));
// Try to allocate almost the full 64 bit address space.
int maxInt1_8 = 1152921504606846975; // 2^60 -1
Expect.throws(() => Pointer<Int64>.allocate(count: maxInt1_8));
Expect.throws(() => allocate<Int64>(count: maxInt1_8));
}
void testPointerAllocateNegative() {
// Passing in -1 will be converted into an unsigned integer. So, it will try
// to allocate SIZE_MAX - 1 + 1 bytes. This will fail as it is the max amount
// of addressable memory on the system.
Expect.throws(() => Pointer<Int8>.allocate(count: -1));
Expect.throws(() => allocate<Int8>(count: -1));
}
+77 -76
View File
@@ -9,6 +9,7 @@ library FfiTest;
import 'dart:ffi';
import "package:expect/expect.dart";
import "package:ffi/ffi.dart";
void main() {
testPointerBasic();
@@ -54,42 +55,42 @@ void main() {
}
void testPointerBasic() {
Pointer<Int64> p = Pointer.allocate();
Pointer<Int64> p = allocate();
p.value = 42;
Expect.equals(42, p.value);
p.free();
free(p);
}
void testPointerFromPointer() {
Pointer<Int64> p = Pointer.allocate();
Pointer<Int64> p = allocate();
p.value = 1337;
int ptr = p.address;
Pointer<Int64> p2 = Pointer.fromAddress(ptr);
Expect.equals(1337, p2.value);
p.free();
free(p);
}
void testPointerPointerArithmetic() {
Pointer<Int64> p = Pointer.allocate(count: 2);
Pointer<Int64> p = allocate(count: 2);
Pointer<Int64> p2 = p.elementAt(1);
p2.value = 100;
Pointer<Int64> p3 = p.offsetBy(8);
Expect.equals(100, p3.value);
p.free();
free(p);
}
void testPointerPointerArithmeticSizes() {
Pointer<Int64> p = Pointer.allocate(count: 2);
Pointer<Int64> p = allocate(count: 2);
Pointer<Int64> p2 = p.elementAt(1);
int addr = p.address;
Expect.equals(addr + 8, p2.address);
p.free();
free(p);
Pointer<Int32> p3 = Pointer.allocate(count: 2);
Pointer<Int32> p3 = allocate(count: 2);
Pointer<Int32> p4 = p3.elementAt(1);
addr = p3.address;
Expect.equals(addr + 4, p4.address);
p3.free();
free(p3);
}
void testPointerAllocateZero() {
@@ -101,19 +102,19 @@ void testPointerAllocateZero() {
bool returnedNullPointer = false;
Pointer<Int8> p;
try {
p = Pointer<Int8>.allocate(count: 0);
p = allocate<Int8>(count: 0);
} on Exception {
returnedNullPointer = true;
}
if (!returnedNullPointer) {
p.free();
free(p);
}
}
void testPointerCast() {
Pointer<Int64> p = Pointer.allocate();
Pointer<Int64> p = allocate();
Pointer<Int32> p2 = p.cast(); // gets the correct type args back
p.free();
free(p);
}
void testCastGeneric() {
@@ -121,9 +122,9 @@ void testCastGeneric() {
return p.cast();
}
Pointer<Int16> p = Pointer.allocate();
Pointer<Int16> p = allocate();
Pointer<Int64> p2 = generic(p);
p.free();
free(p);
}
void testCastGeneric2() {
@@ -131,41 +132,41 @@ void testCastGeneric2() {
return p.cast();
}
Pointer<Int16> p = Pointer.allocate();
Pointer<Int16> p = allocate();
Pointer<Int64> p2 = generic(p);
p.free();
free(p);
}
void testCastNativeType() {
Pointer<Int64> p = Pointer.allocate();
Pointer<Int64> p = allocate();
p.cast<Pointer>();
p.free();
free(p);
}
void testCondensedNumbersInt8() {
Pointer<Int8> p = Pointer.allocate(count: 8);
Pointer<Int8> p = allocate(count: 8);
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
p[i] = i * 3;
}
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
Expect.equals(i * 3, p[i]);
}
p.free();
free(p);
}
void testCondensedNumbersFloat() {
Pointer<Float> p = Pointer.allocate(count: 8);
Pointer<Float> p = allocate(count: 8);
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
p[i] = 1.511366173271439e-13;
}
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
Expect.equals(1.511366173271439e-13, p[i]);
}
p.free();
free(p);
}
void testRangeInt8() {
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
p.value = 127;
Expect.equals(127, p.value);
p.value = -128;
@@ -180,11 +181,11 @@ void testRangeInt8() {
Expect.equals(0x000000000000007F, 127);
p.value = -129;
Expect.equals(127, p.value); // truncated
p.free();
free(p);
}
void testRangeUint8() {
Pointer<Uint8> p = Pointer.allocate();
Pointer<Uint8> p = allocate();
p.value = 255;
Expect.equals(255, p.value);
p.value = 0;
@@ -199,11 +200,11 @@ void testRangeUint8() {
Expect.equals(0x00000000000000FF, 255);
p.value = -1;
Expect.equals(255, p.value); // truncated
p.free();
free(p);
}
void testRangeInt16() {
Pointer<Int16> p = Pointer.allocate();
Pointer<Int16> p = allocate();
p.value = 0x7FFF;
Expect.equals(0x7FFF, p.value);
p.value = -0x8000;
@@ -212,11 +213,11 @@ void testRangeInt16() {
Expect.equals(0xFFFFFFFFFFFF8000, p.value); // truncated and sign extended
p.value = -0x8001;
Expect.equals(0x7FFF, p.value); // truncated
p.free();
free(p);
}
void testRangeUint16() {
Pointer<Uint16> p = Pointer.allocate();
Pointer<Uint16> p = allocate();
p.value = 0xFFFF;
Expect.equals(0xFFFF, p.value);
p.value = 0;
@@ -225,11 +226,11 @@ void testRangeUint16() {
Expect.equals(0, p.value); // truncated
p.value = -1;
Expect.equals(0xFFFF, p.value); // truncated
p.free();
free(p);
}
void testRangeInt32() {
Pointer<Int32> p = Pointer.allocate();
Pointer<Int32> p = allocate();
p.value = 0x7FFFFFFF;
Expect.equals(0x7FFFFFFF, p.value);
p.value = -0x80000000;
@@ -238,11 +239,11 @@ void testRangeInt32() {
Expect.equals(0xFFFFFFFF80000000, p.value); // truncated and sign extended
p.value = -0x80000001;
Expect.equals(0x7FFFFFFF, p.value); // truncated
p.free();
free(p);
}
void testRangeUint32() {
Pointer<Uint32> p = Pointer.allocate();
Pointer<Uint32> p = allocate();
p.value = 0xFFFFFFFF;
Expect.equals(0xFFFFFFFF, p.value);
p.value = 0;
@@ -251,20 +252,20 @@ void testRangeUint32() {
Expect.equals(0, p.value); // truncated
p.value = -1;
Expect.equals(0xFFFFFFFF, p.value); // truncated
p.free();
free(p);
}
void testRangeInt64() {
Pointer<Int64> p = Pointer.allocate();
Pointer<Int64> p = allocate();
p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
p.value = -0x8000000000000000; // -2 ^ 63
Expect.equals(-0x8000000000000000, p.value);
p.free();
free(p);
}
void testRangeUint64() {
Pointer<Uint64> p = Pointer.allocate();
Pointer<Uint64> p = allocate();
p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
p.value = -0x8000000000000000; // -2 ^ 63 interpreted as 2 ^ 63
@@ -275,84 +276,84 @@ void testRangeUint64() {
p.value = -1; // -1 interpreted as 2 ^ 64 - 1
Expect.equals(-1, p.value);
Expect.equals(0xFFFFFFFFFFFFFFFF, p.value);
p.free();
free(p);
}
void testRangeIntPtr() {
Pointer<IntPtr> p = Pointer.allocate();
Pointer<IntPtr> p = allocate();
int pAddr = p.address;
p.value = pAddr; // its own address should fit
p.value = 0x7FFFFFFF; // and 32 bit addresses should fit
Expect.equals(0x7FFFFFFF, p.value);
p.value = -0x80000000;
Expect.equals(-0x80000000, p.value);
p.free();
free(p);
}
void testFloat() {
Pointer<Float> p = Pointer.allocate();
Pointer<Float> p = allocate();
p.value = 1.511366173271439e-13;
Expect.equals(1.511366173271439e-13, p.value);
p.value = 1.4260258159703532e-105; // float does not have enough precision
Expect.notEquals(1.4260258159703532e-105, p.value);
p.free();
free(p);
}
void testDouble() {
Pointer<Double> p = Pointer.allocate();
Pointer<Double> p = allocate();
p.value = 1.4260258159703532e-105;
Expect.equals(1.4260258159703532e-105, p.value);
p.free();
free(p);
}
void testVoid() {
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<IntPtr> p1 = allocate();
Pointer<Void> p2 = p1.cast(); // make this dart pointer opaque
p2.address; // we can print the address
p2.free();
free(p2);
}
void testPointerPointer() {
Pointer<Int16> p = Pointer.allocate();
Pointer<Int16> p = allocate();
p.value = 17;
Pointer<Pointer<Int16>> p2 = Pointer.allocate();
Pointer<Pointer<Int16>> p2 = allocate();
p2.value = p;
Expect.equals(17, p2.value.value);
p2.free();
p.free();
free(p2);
free(p);
}
void testPointerPointerNull() {
Pointer<Pointer<Int8>> pointerToPointer = Pointer.allocate();
Pointer<Pointer<Int8>> pointerToPointer = allocate();
Pointer<Int8> value = nullptr.cast();
pointerToPointer.value = value;
value = pointerToPointer.value;
Expect.equals(value, nullptr);
value = Pointer.allocate();
value = allocate();
pointerToPointer.value = value;
value = pointerToPointer.value;
Expect.isNotNull(value);
value.free();
free(value);
value = nullptr.cast();
pointerToPointer.value = value;
value = pointerToPointer.value;
Expect.equals(value, nullptr);
pointerToPointer.free();
free(pointerToPointer);
}
void testPointerStoreNull() {
int i = null;
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
Expect.throws(() => p.value = i);
p.free();
free(p);
double d = null;
Pointer<Float> p2 = Pointer.allocate();
Pointer<Float> p2 = allocate();
Expect.throws(() => p2.value = d);
p2.free();
free(p2);
Pointer<Void> x = null;
Pointer<Pointer<Void>> p3 = Pointer.allocate();
Pointer<Pointer<Void>> p3 = allocate();
Expect.throws(() => p3.value = x);
p3.free();
free(p3);
}
void testSizeOf() {
@@ -376,7 +377,7 @@ void testPointerChain(int length) {
head.value = value;
return;
}
Pointer<IntPtr> next = Pointer.allocate();
Pointer<IntPtr> next = allocate();
head.value = next.address;
createChain(next, length - 1, value);
}
@@ -391,14 +392,14 @@ void testPointerChain(int length) {
void freeChain(Pointer<IntPtr> head, int length) {
Pointer<IntPtr> next = Pointer.fromAddress(head.value);
head.free();
free(head);
if (length == 0) {
return;
}
freeChain(next, length - 1);
}
Pointer<IntPtr> head = Pointer.allocate();
Pointer<IntPtr> head = allocate();
createChain(head, length, 512);
int tailValue = getChainValue(head, length);
Expect.equals(512, tailValue);
@@ -406,16 +407,16 @@ void testPointerChain(int length) {
}
void testTypeTest() {
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
Expect.isTrue(p is Pointer);
p.free();
free(p);
}
void testToString() {
Pointer<Int16> p = Pointer.allocate();
Pointer<Int16> p = allocate();
Expect.stringEquals(
"Pointer<Int16>: address=0x", p.toString().substring(0, 26));
p.free();
free(p);
Pointer<Int64> p2 = Pointer.fromAddress(0x123abc);
Expect.stringEquals("Pointer<Int64>: address=0x123abc", p2.toString());
}
@@ -439,29 +440,29 @@ typedef Int8UnOp = Int8 Function(Int8);
void testAllocateGeneric() {
Pointer<T> generic<T extends NativeType>() {
Pointer<T> pointer;
pointer = Pointer.allocate();
pointer = allocate();
return pointer;
}
Pointer p = generic<Int64>();
p.free();
free(p);
}
void testAllocateVoid() {
Expect.throws(() {
Pointer<Void> p = Pointer.allocate();
Pointer<Void> p = allocate();
});
}
void testAllocateNativeFunction() {
Expect.throws(() {
Pointer<NativeFunction<Int8UnOp>> p = Pointer.allocate();
Pointer<NativeFunction<Int8UnOp>> p = allocate();
});
}
void testAllocateNativeType() {
Expect.throws(() {
Pointer.allocate();
allocate();
});
}
@@ -495,7 +496,7 @@ void testSizeOfNativeType() {
}
void testDynamicInvocation() {
dynamic p = Pointer<Int8>.allocate();
dynamic p = allocate<Int8>();
Expect.throws(() {
final int i = p.value;
});
@@ -503,5 +504,5 @@ void testDynamicInvocation() {
p.elementAt(5); // Works, but is slow.
final int addr = p.address;
final Pointer<Int16> p2 = p.cast<Int16>();
p.free();
free(p);
}
+3 -2
View File
@@ -11,10 +11,11 @@
// VMOptions=--enable-ffi=false
import 'dart:ffi'; //# 01: compile-time error, runtime error
import 'package:ffi/ffi.dart'; //# 01: compile-time error, runtime error
void main() {
Pointer<Int8> p = //# 01: compile-time error, runtime error
Pointer.allocate(); //# 01: compile-time error, runtime error
allocate(); //# 01: compile-time error, runtime error
print(p.address); //# 01: compile-time error, runtime error
p.free(); //# 01: compile-time error, runtime error
free(p); //# 01: compile-time error, runtime error
}
+15 -14
View File
@@ -5,6 +5,7 @@
import 'dart:ffi';
import "package:expect/expect.dart";
import "package:ffi/ffi.dart";
main(List<String> arguments) {
for (int i = 0; i < 100; i++) {
@@ -16,37 +17,37 @@ main(List<String> arguments) {
}
testStoreLoad() {
final p = Pointer<Int8>.allocate(count: 2);
final p = allocate<Int8>(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);
final p1 = allocate<Double>(count: 2);
p1.value = 10.0;
Expect.approxEquals(10.0, p1.value);
p1[1] = 20.0;
Expect.approxEquals(20.0, p1[1]);
p1.free();
free(p1);
final p2 = Pointer<Pointer<Int8>>.allocate(count: 2);
final p2 = allocate<Pointer<Int8>>(count: 2);
p2.value = p;
Expect.equals(p, p2.value);
p2[1] = p;
Expect.equals(p, p2[1]);
p2.free();
p.free();
free(p2);
free(p);
final p3 = Pointer<Foo>.allocate();
final p3 = allocate<Foo>();
Foo foo = p3.ref;
foo.a = 1;
Expect.equals(1, foo.a);
p3.free();
free(p3);
}
/// With extension methods, the receiver position can be null.
testNullReceivers() {
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
Pointer<Int8> p4 = null;
Expect.throws(() => Expect.equals(10, p4.value));
@@ -59,20 +60,20 @@ testNullReceivers() {
Pointer<Foo> p6 = null;
Expect.throws(() => Expect.equals(10, p6.ref));
p.free();
free(p);
}
testNullArguments() {
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
Expect.throws(() => p.value = null);
p.free();
free(p);
}
testReifiedGeneric() {
final p = Pointer<Pointer<Int8>>.allocate();
final p = allocate<Pointer<Int8>>();
Pointer<Pointer<NativeType>> p2 = p;
Expect.isTrue(p2.value is Pointer<Int8>);
p.free();
free(p);
}
class Foo extends Struct<Foo> {
+47 -46
View File
@@ -7,6 +7,7 @@ import 'dart:math';
import 'dart:typed_data';
import 'package:expect/expect.dart';
import "package:ffi/ffi.dart";
main() {
testInt8Load();
@@ -41,174 +42,174 @@ main() {
void testInt8Load() {
// Load
Pointer<Int8> ptr = Pointer.allocate();
Pointer<Int8> ptr = allocate();
ptr.value = 0xff;
Int8List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testInt8Store() {
// Store
Pointer<Int8> ptr = Pointer.allocate();
Pointer<Int8> ptr = allocate();
Int8List list = ptr.asExternalTypedData();
list[0] = 0xff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, -1);
ptr.free();
free(ptr);
}
void testUint8Load() {
// Load
Pointer<Uint8> ptr = Pointer.allocate();
Pointer<Uint8> ptr = allocate();
ptr.value = 0xff;
Uint8List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xff);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testUint8Store() {
// Store
Pointer<Uint8> ptr = Pointer.allocate();
Pointer<Uint8> ptr = allocate();
Uint8List list = ptr.asExternalTypedData();
list[0] = 0xff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, 0xff);
ptr.free();
free(ptr);
}
void testInt16Load() {
// Load
Pointer<Int16> ptr = Pointer.allocate();
Pointer<Int16> ptr = allocate();
ptr.value = 0xffff;
Int16List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testInt16Store() {
// Store
Pointer<Int16> ptr = Pointer.allocate();
Pointer<Int16> ptr = allocate();
Int16List list = ptr.asExternalTypedData();
list[0] = 0xffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, -1);
ptr.free();
free(ptr);
}
void testUint16Load() {
// Load
Pointer<Uint16> ptr = Pointer.allocate();
Pointer<Uint16> ptr = allocate();
ptr.value = 0xffff;
Uint16List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffff);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testUint16Store() {
// Store
Pointer<Uint16> ptr = Pointer.allocate();
Pointer<Uint16> ptr = allocate();
Uint16List list = ptr.asExternalTypedData();
list[0] = 0xffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, 0xffff);
ptr.free();
free(ptr);
}
void testInt32Load() {
// Load
Pointer<Int32> ptr = Pointer.allocate();
Pointer<Int32> ptr = allocate();
ptr.value = 0xffffffff;
Int32List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testInt32Store() {
// Store
Pointer<Int32> ptr = Pointer.allocate();
Pointer<Int32> ptr = allocate();
Int32List list = ptr.asExternalTypedData();
list[0] = 0xffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, -1);
ptr.free();
free(ptr);
}
void testUint32Load() {
// Load
Pointer<Uint32> ptr = Pointer.allocate();
Pointer<Uint32> ptr = allocate();
ptr.value = 0xffffffff;
Uint32List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffffffff);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testUint32Store() {
// Store
Pointer<Uint32> ptr = Pointer.allocate();
Pointer<Uint32> ptr = allocate();
Uint32List list = ptr.asExternalTypedData();
list[0] = 0xffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, 0xffffffff);
ptr.free();
free(ptr);
}
void testInt64Load() {
// Load
Pointer<Int64> ptr = Pointer.allocate();
Pointer<Int64> ptr = allocate();
ptr.value = 0xffffffffffffffff;
Int64List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testInt64Store() {
// Store
Pointer<Int64> ptr = Pointer.allocate();
Pointer<Int64> ptr = allocate();
Int64List list = ptr.asExternalTypedData();
list[0] = 0xffffffffffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, -1);
ptr.free();
free(ptr);
}
void testUint64Load() {
// Load
Pointer<Uint64> ptr = Pointer.allocate();
Pointer<Uint64> ptr = allocate();
ptr.value = 0xffffffffffffffff;
Uint64List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffffffffffffffff);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testUint64Store() {
// Store
Pointer<Uint64> ptr = Pointer.allocate();
Pointer<Uint64> ptr = allocate();
Uint64List list = ptr.asExternalTypedData();
list[0] = 0xffffffffffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, 0xffffffffffffffff);
ptr.free();
free(ptr);
}
void testIntPtr() {
bool is32Bit = sizeOf<IntPtr>() == 4;
Pointer<IntPtr> ptr = Pointer.allocate();
Pointer<IntPtr> ptr = allocate();
final array = ptr.asExternalTypedData();
if (is32Bit) {
Expect.type<Int32List>(array);
} else {
Expect.type<Int64List>(array);
}
ptr.free();
free(ptr);
}
double maxFloat = (2 - pow(2, -23)) * pow(2, 127);
@@ -216,47 +217,47 @@ double maxDouble = (2 - pow(2, -52)) * pow(2, pow(2, 10) - 1);
void testFloatLoad() {
// Load
Pointer<Float> ptr = Pointer.allocate();
Pointer<Float> ptr = allocate();
ptr.value = maxFloat;
Float32List list = ptr.asExternalTypedData();
Expect.equals(list[0], maxFloat);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testFloatStore() {
// Store
Pointer<Float> ptr = Pointer.allocate();
Pointer<Float> ptr = allocate();
Float32List list = ptr.asExternalTypedData();
list[0] = maxFloat;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, maxFloat);
ptr.free();
free(ptr);
}
void testDoubleLoad() {
// Load
Pointer<Double> ptr = Pointer.allocate();
Pointer<Double> ptr = allocate();
ptr.value = maxDouble;
Float64List list = ptr.asExternalTypedData();
Expect.equals(list[0], maxDouble);
Expect.equals(list.length, 1);
ptr.free();
free(ptr);
}
void testDoubleStore() {
// Store
Pointer<Double> ptr = Pointer.allocate();
Pointer<Double> ptr = allocate();
Float64List list = ptr.asExternalTypedData();
list[0] = maxDouble;
Expect.equals(list.length, 1);
Expect.equals(ptr.value, maxDouble);
ptr.free();
free(ptr);
}
void testArrayLoad() {
const int count = 0x100;
Pointer<Int32> ptr = Pointer.allocate(count: count);
Pointer<Int32> ptr = allocate(count: count);
for (int i = 0; i < count; ++i) {
ptr[i] = i;
}
@@ -264,12 +265,12 @@ void testArrayLoad() {
for (int i = 0; i < count; ++i) {
Expect.equals(array[i], i);
}
ptr.free();
free(ptr);
}
void testArrayStore() {
const int count = 0x100;
Pointer<Int32> ptr = Pointer.allocate(count: count);
Pointer<Int32> ptr = allocate(count: count);
Int32List array = ptr.asExternalTypedData(count: count);
for (int i = 0; i < count; ++i) {
array[i] = i;
@@ -277,7 +278,7 @@ void testArrayStore() {
for (int i = 0; i < count; ++i) {
Expect.equals(ptr[i], i);
}
ptr.free();
free(ptr);
}
void testNegativeArray() {
+7 -6
View File
@@ -14,6 +14,7 @@ import 'dart:ffi';
import 'dylib_utils.dart';
import "package:expect/expect.dart";
import "package:ffi/ffi.dart";
import 'coordinate.dart';
import 'very_large_struct.dart';
@@ -47,8 +48,8 @@ void testFunctionWithStruct() {
Expect.approxEquals(42.0, result.x);
Expect.approxEquals(84.0, result.y);
c1.free();
c2.free();
free(c1);
free(c2);
}
/// pass an array of structs to a c funtion
@@ -57,7 +58,7 @@ void testFunctionWithStructArray() {
ffiTestFunctions.lookup("CoordinateElemAt1");
NativeCoordinateOp f1 = p1.asFunction();
Coordinate c1 = Pointer<Coordinate>.allocate(count: 3).ref;
Coordinate c1 = allocate<Coordinate>(count: 3).ref;
Coordinate c2 = c1.addressOf[1];
Coordinate c3 = c1.addressOf[2];
c1.x = 10.0;
@@ -74,7 +75,7 @@ void testFunctionWithStructArray() {
Expect.approxEquals(20.0, result.x);
Expect.approxEquals(20.0, result.y);
c1.addressOf.free();
free(c1.addressOf);
}
typedef VeryLargeStructSum = int Function(Pointer<VeryLargeStruct>);
@@ -85,7 +86,7 @@ void testFunctionWithVeryLargeStruct() {
ffiTestFunctions.lookup("SumVeryLargeStruct");
VeryLargeStructSum f = p1.asFunction();
VeryLargeStruct vls1 = Pointer<VeryLargeStruct>.allocate(count: 2).ref;
VeryLargeStruct vls1 = allocate<VeryLargeStruct>(count: 2).ref;
VeryLargeStruct vls2 = vls1.addressOf[1];
List<VeryLargeStruct> structs = [vls1, vls2];
for (VeryLargeStruct struct in structs) {
@@ -116,5 +117,5 @@ void testFunctionWithVeryLargeStruct() {
result = f(vls2.addressOf);
Expect.equals(2048, result);
vls1.addressOf.free();
free(vls1.addressOf);
}
+9 -8
View File
@@ -19,6 +19,7 @@ import 'dart:ffi';
import 'dylib_utils.dart';
import "package:ffi/ffi.dart";
import "package:expect/expect.dart";
void main() {
@@ -54,11 +55,11 @@ typedef BinaryOp = int Function(int, int);
typedef GenericBinaryOp<T> = int Function(int, T);
void testNativeFunctionFromCast() {
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<IntPtr> p1 = allocate();
Pointer<NativeFunction<NativeBinaryOp>> p2 = p1.cast();
p2.asFunction<BinaryOp>();
p2.asFunction<GenericBinaryOp<int>>();
p1.free();
free(p1);
}
typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
@@ -324,14 +325,14 @@ Int64PointerUnOp assign1337Index1 = ffiTestFunctions
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
void testNativeFunctionPointer() {
Pointer<Int64> p2 = Pointer.allocate(count: 2);
Pointer<Int64> p2 = allocate(count: 2);
p2.value = 42;
p2[1] = 1000;
Pointer<Int64> result = assign1337Index1(p2);
Expect.equals(1337, result.value);
Expect.equals(1337, p2[1]);
Expect.equals(p2.elementAt(1).address, result.address);
p2.free();
free(p2);
}
void testNullInt() {
@@ -357,10 +358,10 @@ void testNullPointers() {
Pointer<Int64> result = nullableInt64ElemAt1(nullptr.cast());
Expect.equals(result, nullptr);
Pointer<Int64> p2 = Pointer.allocate(count: 2);
Pointer<Int64> p2 = allocate(count: 2);
result = nullableInt64ElemAt1(p2);
Expect.notEquals(result, nullptr);
p2.free();
free(p2);
}
typedef NativeFloatPointerToBool = Uint8 Function(Pointer<Float>);
@@ -370,13 +371,13 @@ FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
void testFloatRounding() {
Pointer<Float> p2 = Pointer.allocate();
Pointer<Float> p2 = allocate();
p2.value = 1337.0;
int result = isRoughly1337(p2);
Expect.equals(1, result);
p2.free();
free(p2);
}
typedef NativeFloatToVoid = Void Function(Float);
-1
View File
@@ -12,7 +12,6 @@ import 'dart:ffi';
import "package:expect/expect.dart";
import 'utf8.dart';
import 'dylib_utils.dart';
DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+49 -56
View File
@@ -63,36 +63,36 @@
import 'dart:ffi';
import "package:expect/expect.dart";
import "package:ffi/ffi.dart";
// ===== a.value = b ======
// The tests follow table cells left to right, top to bottom.
void store1() {
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Int8> b = Pointer<Int8>.allocate();
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
final Pointer<Int8> b = allocate<Int8>();
a.value = b;
a.free();
b.free();
free(a);
free(b);
}
void store2() {
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
final Pointer<NativeType> b =
Pointer<Int8>.allocate(); // Reified Pointer<Int8> at runtime.
allocate<Int8>(); // Reified Pointer<Int8> at runtime.
// Successful implicit downcast of argument at runtime.
// Should succeed now, should statically be rejected when NNBD lands.
a.value = b;
a.free();
b.free();
free(a);
free(b);
}
void store3() {
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<NativeType> b =
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
// Failing implicit downcast of argument at runtime.
// Should fail now at runtime, should statically be rejected when NNBD lands.
@@ -100,130 +100,124 @@ void store3() {
a.value = b;
});
a.free();
b.free();
free(a);
free(b);
}
void store4() {
// Reified as Pointer<Pointer<Int8>> at runtime.
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
final Pointer<Int8> b = Pointer<Int8>.allocate();
final Pointer<Int8> b = allocate<Int8>();
a.value = b;
a.free();
b.free();
free(a);
free(b);
}
void store5() {
// Reified as Pointer<Pointer<Int8>> at runtime.
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
final Pointer<NativeType> b =
Pointer<Int8>.allocate(); // Reified as Pointer<Int8> at runtime.
allocate<Int8>(); // Reified as Pointer<Int8> at runtime.
a.value = b;
a.free();
b.free();
free(a);
free(b);
}
void store6() {
// Reified as Pointer<Pointer<Int8>> at runtime.
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<NativeType> b =
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
// Fails on type check of argument.
Expect.throws(() {
a.value = b;
});
a.free();
b.free();
free(a);
free(b);
}
void store7() {
final Pointer<Pointer<NativeType>> a =
Pointer<Pointer<NativeType>>.allocate();
final Pointer<Int8> b = Pointer<Int8>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
final Pointer<Int8> b = allocate<Int8>();
a.value = b;
a.free();
b.free();
free(a);
free(b);
}
void store8() {
final Pointer<Pointer<NativeType>> a =
Pointer<Pointer<NativeType>>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
// Reified as Pointer<Int8> at runtime.
final Pointer<NativeType> b = Pointer<Int8>.allocate();
final Pointer<NativeType> b = allocate<Int8>();
a.value = b;
a.free();
b.free();
free(a);
free(b);
}
void store9() {
final Pointer<Pointer<NativeType>> a =
Pointer<Pointer<NativeType>>.allocate();
final Pointer<NativeType> b =
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
a.value = b;
a.free();
b.free();
free(a);
free(b);
}
// ====== b = a.value ======
// The tests follow table cells left to right, top to bottom.
void load1() {
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
Pointer<Int8> b = a.value;
Expect.type<Pointer<Int8>>(b);
a.free();
free(a);
}
void load2() {
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
Pointer<NativeType> b = a.value;
Expect.type<Pointer<Int8>>(b);
a.free();
free(a);
}
void load3() {
// Reified as Pointer<Pointer<Int8>> at runtime.
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
Pointer<Int8> b = a.value;
Expect.type<Pointer<Int8>>(b);
a.free();
free(a);
}
void load4() {
// Reified as Pointer<Pointer<Int8>> at runtime.
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
// Return value runtime type is Pointer<Int8>.
Pointer<NativeType> b = a.value;
Expect.type<Pointer<Int8>>(b);
a.free();
free(a);
}
void load5() {
final Pointer<Pointer<NativeType>> a =
Pointer<Pointer<NativeType>>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
// Failing implicit downcast of return value at runtime.
// Should fail now at runtime, should statically be rejected when NNBD lands.
@@ -231,17 +225,16 @@ void load5() {
Pointer<Int8> b = a.value;
});
a.free();
free(a);
}
void load6() {
final Pointer<Pointer<NativeType>> a =
Pointer<Pointer<NativeType>>.allocate();
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
Pointer<NativeType> b = a.value;
Expect.type<Pointer<NativeType>>(b);
a.free();
free(a);
}
void main() {
+20 -18
View File
@@ -10,6 +10,8 @@ library FfiTest;
import 'dart:ffi';
import "package:ffi/ffi.dart";
import 'dylib_utils.dart';
void main() {
@@ -56,20 +58,20 @@ void testGetGeneric() {
return result;
}
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
p.value = 123;
Pointer loseType = p;
generic(loseType);
p.free();
free(p);
}
void testGetGeneric2() {
T generic<T extends Object>() {
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
p.value = 123;
T result;
result = p.value; //# 21: compile-time error
p.free();
free(p);
return result;
}
@@ -77,12 +79,12 @@ void testGetGeneric2() {
}
void testGetVoid() {
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<IntPtr> p1 = allocate();
Pointer<Void> p2 = p1.cast();
p2.value; //# 22: compile-time error
p1.free();
free(p1);
}
void testGetNativeFunction() {
@@ -95,14 +97,14 @@ void testGetNativeType() {
}
void testGetTypeMismatch() {
Pointer<Pointer<Int16>> p = Pointer.allocate();
Pointer<Pointer<Int16>> p = allocate();
Pointer<Int16> typedNull = nullptr.cast();
p.value = typedNull;
// this fails to compile due to type mismatch
Pointer<Int8> p2 = p.value; //# 25: compile-time error
p.free();
free(p);
}
void testSetGeneric() {
@@ -110,30 +112,30 @@ void testSetGeneric() {
p.value = 123; //# 26: compile-time error
}
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
p.value = 123;
Pointer loseType = p;
generic(loseType);
p.free();
free(p);
}
void testSetGeneric2() {
void generic<T extends Object>(T arg) {
Pointer<Int8> p = Pointer.allocate();
Pointer<Int8> p = allocate();
p.value = arg; //# 27: compile-time error
p.free();
free(p);
}
generic<int>(123);
}
void testSetVoid() {
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<IntPtr> p1 = allocate();
Pointer<Void> p2 = p1.cast();
p2.value = 1234; //# 28: compile-time error
p1.free();
free(p1);
}
void testSetNativeFunction() {
@@ -148,16 +150,16 @@ void testSetNativeType() {
void testSetTypeMismatch() {
// the pointer to pointer types must match up
Pointer<Int8> pHelper = Pointer.allocate();
Pointer<Int8> pHelper = allocate();
pHelper.value = 123;
Pointer<Pointer<Int16>> p = Pointer.allocate();
Pointer<Pointer<Int16>> p = allocate();
// this fails to compile due to type mismatch
p.value = pHelper; //# 40: compile-time error
pHelper.free();
p.free();
free(pHelper);
free(p);
}
void testAsFunctionGeneric() {
+12 -13
View File
@@ -11,10 +11,10 @@ library FfiTest;
import 'dart:ffi';
import "package:expect/expect.dart";
import "package:ffi/ffi.dart";
import 'coordinate_bare.dart' as bare;
import 'coordinate.dart';
import 'utf8.dart';
void main() {
for (int i = 0; i < 100; i++) {
@@ -44,14 +44,14 @@ void testStructAllocate() {
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(10.0, currentCoordinate.x);
c1.free();
c2.free();
c3.free();
free(c1);
free(c2);
free(c3);
}
/// allocates coordinates consecutively in c memory
void testStructFromAddress() {
Pointer<Coordinate> c1 = Pointer.allocate(count: 3);
Pointer<Coordinate> c1 = allocate(count: 3);
Pointer<Coordinate> c2 = c1.elementAt(1);
Pointer<Coordinate> c3 = c1.elementAt(2);
c1.ref
@@ -76,7 +76,7 @@ void testStructFromAddress() {
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(10.0, currentCoordinate.x);
c1.free();
free(c1);
}
void testStructWithNulls() {
@@ -87,14 +87,13 @@ void testStructWithNulls() {
Expect.notEquals(coordinate.ref.next, nullptr);
coordinate.ref.next = nullptr.cast();
Expect.equals(coordinate.ref.next, nullptr);
coordinate.free();
free(coordinate);
}
void testBareStruct() {
int structSize = sizeOf<Double>() * 2 + sizeOf<IntPtr>();
bare.Coordinate c1 = Pointer<Uint8>.allocate(count: structSize * 3)
.cast<bare.Coordinate>()
.ref;
bare.Coordinate c1 =
allocate<Uint8>(count: structSize * 3).cast<bare.Coordinate>().ref;
bare.Coordinate c2 =
c1.addressOf.offsetBy(structSize).cast<bare.Coordinate>().ref;
bare.Coordinate c3 =
@@ -118,19 +117,19 @@ void testBareStruct() {
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(10.0, currentCoordinate.x);
c1.addressOf.free();
free(c1.addressOf);
}
void testTypeTest() {
Coordinate c = Coordinate.allocate(10, 10, nullptr.cast<Coordinate>());
Expect.isTrue(c is Struct);
Expect.isTrue(c is Struct<Coordinate>);
c.addressOf.free();
free(c.addressOf);
}
void testUtf8() {
final String test = 'Hasta Mañana';
final Pointer<Utf8> medium = Utf8.toUtf8(test);
Expect.equals(test, Utf8.fromUtf8(medium));
medium.free();
free(medium);
}
-36
View File
@@ -1,36 +0,0 @@
// 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.
library Utf8;
import 'dart:convert';
import 'dart:ffi';
/// Sample non-struct Pointer wrapper for dart:ffi library.
class Utf8 extends Struct<Utf8> {
@Uint8()
int char;
static String fromUtf8(Pointer<Utf8> str) {
List<int> units = [];
int len = 0;
while (true) {
int char = str[len++].char;
if (char == 0) break;
units.add(char);
}
return Utf8Decoder().convert(units);
}
static Pointer<Utf8> toUtf8(String s) {
List<int> units = Utf8Encoder().convert(s);
Pointer<Utf8> result =
Pointer<Utf8>.allocate(count: units.length + 1).cast();
for (int i = 0; i < units.length; i++) {
result[i].char = units[i];
}
result[units.length].char = 0;
return result;
}
}