[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:
committed by
commit-bot@chromium.org
parent
18aed26e83
commit
63d3012e68
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}');
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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,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
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user