mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 17:04:56 +00:00
[vm/ffi] Migrate tests/samples/benchmarks to extension methods
I used the regex replaces documented on the `load` and `store` deprecated methods. I manually replaced some `.val` to `.ref` when a regex could not detect whether something was a primitive value or a struct. Issue: https://github.com/dart-lang/sdk/issues/37773 Change-Id: I3534b6dd00d9ac45fa1a11fe75c80fb3cccc07dc Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-dartkb-linux-debug-simarm64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-dartkb-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-mac-debug-simdbc64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-reload-mac-release-simdbc64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-precomp-mac-release-simarm_x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118993 Reviewed-by: Samir Jindel <sjindel@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
parent
597cd06aec
commit
ee0b1df4a6
|
@ -29,7 +29,7 @@ Uint8List toUint8List(Bytes bytes, int length) {
|
||||||
final result = Uint8List(length);
|
final result = Uint8List(length);
|
||||||
final uint8bytes = bytes.asUint8Pointer();
|
final uint8bytes = bytes.asUint8Pointer();
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
result[i] = uint8bytes.elementAt(i).load<int>();
|
result[i] = uint8bytes[i];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ void copyFromUint8ListToTarget(Uint8List source, Data target) {
|
||||||
final int length = source.length;
|
final int length = source.length;
|
||||||
final uint8target = target.asUint8Pointer();
|
final uint8target = target.asUint8Pointer();
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
uint8target.offsetBy(i).store(source[i]);
|
uint8target[i] = source[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ String hash(Pointer<Data> data, int length, Pointer<EVP_MD> hashAlgorithm) {
|
||||||
Pointer<Uint8>.allocate(count: resultSize).cast();
|
Pointer<Uint8>.allocate(count: resultSize).cast();
|
||||||
EVP_DigestFinal(context, result, nullptr.cast());
|
EVP_DigestFinal(context, result, nullptr.cast());
|
||||||
EVP_MD_CTX_free(context);
|
EVP_MD_CTX_free(context);
|
||||||
final String hash = base64Encode(toUint8List(result.load(), resultSize));
|
final String hash = base64Encode(toUint8List(result.ref, resultSize));
|
||||||
result.free();
|
result.free();
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ class DigestCMemory extends BenchmarkBase {
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
data = Pointer<Uint8>.allocate(count: L).cast();
|
data = Pointer<Uint8>.allocate(count: L).cast();
|
||||||
copyFromUint8ListToTarget(inventData(L), data.load());
|
copyFromUint8ListToTarget(inventData(L), data.ref);
|
||||||
hash(data, L, hashAlgorithm);
|
hash(data, L, hashAlgorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ class DigestDartMemory extends BenchmarkBase {
|
||||||
void setup() {
|
void setup() {
|
||||||
data = inventData(L);
|
data = inventData(L);
|
||||||
final Pointer<Data> dataInC = Pointer<Uint8>.allocate(count: L).cast();
|
final Pointer<Data> dataInC = Pointer<Uint8>.allocate(count: L).cast();
|
||||||
copyFromUint8ListToTarget(data, dataInC.load());
|
copyFromUint8ListToTarget(data, dataInC.ref);
|
||||||
hash(dataInC, L, hashAlgorithm);
|
hash(dataInC, L, hashAlgorithm);
|
||||||
dataInC.free();
|
dataInC.free();
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ class DigestDartMemory extends BenchmarkBase {
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
final Pointer<Data> dataInC = Pointer<Uint8>.allocate(count: L).cast();
|
final Pointer<Data> dataInC = Pointer<Uint8>.allocate(count: L).cast();
|
||||||
copyFromUint8ListToTarget(data, dataInC.load());
|
copyFromUint8ListToTarget(data, dataInC.ref);
|
||||||
final String result = hash(dataInC, L, hashAlgorithm);
|
final String result = hash(dataInC, L, hashAlgorithm);
|
||||||
dataInC.free();
|
dataInC.free();
|
||||||
if (result != expectedHash) {
|
if (result != expectedHash) {
|
||||||
|
|
|
@ -12,14 +12,14 @@ class EVP_MD_CTX extends Struct<EVP_MD_CTX> {}
|
||||||
|
|
||||||
/// Type for `void*` used to represent opaque data.
|
/// Type for `void*` used to represent opaque data.
|
||||||
class Data extends Struct<Data> {
|
class Data extends Struct<Data> {
|
||||||
static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().load();
|
static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().ref;
|
||||||
|
|
||||||
Pointer<Uint8> asUint8Pointer() => this.addressOf.cast();
|
Pointer<Uint8> asUint8Pointer() => this.addressOf.cast();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type for `uint8_t*` used to represent byte data.
|
/// Type for `uint8_t*` used to represent byte data.
|
||||||
class Bytes extends Struct<Bytes> {
|
class Bytes extends Struct<Bytes> {
|
||||||
static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().load();
|
static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().ref;
|
||||||
|
|
||||||
Pointer<Uint8> asUint8Pointer() => this.addressOf.cast();
|
Pointer<Uint8> asUint8Pointer() => this.addressOf.cast();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,74 +19,74 @@ import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
void doStoreInt8(Pointer<Int8> pointer, int length) {
|
void doStoreInt8(Pointer<Int8> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreUint8(Pointer<Uint8> pointer, int length) {
|
void doStoreUint8(Pointer<Uint8> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreInt16(Pointer<Int16> pointer, int length) {
|
void doStoreInt16(Pointer<Int16> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreUint16(Pointer<Uint16> pointer, int length) {
|
void doStoreUint16(Pointer<Uint16> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreInt32(Pointer<Int32> pointer, int length) {
|
void doStoreInt32(Pointer<Int32> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreUint32(Pointer<Uint32> pointer, int length) {
|
void doStoreUint32(Pointer<Uint32> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreInt64(Pointer<Int64> pointer, int length) {
|
void doStoreInt64(Pointer<Int64> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreUint64(Pointer<Uint64> pointer, int length) {
|
void doStoreUint64(Pointer<Uint64> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1);
|
pointer[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreFloat(Pointer<Float> pointer, int length) {
|
void doStoreFloat(Pointer<Float> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1.0);
|
pointer[i] = 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreDouble(Pointer<Double> pointer, int length) {
|
void doStoreDouble(Pointer<Double> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(1.0);
|
pointer[i] = 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStorePointer(
|
void doStorePointer(
|
||||||
Pointer<Pointer<Int8>> pointer, int length, Pointer<Int8> data) {
|
Pointer<Pointer<Int8>> pointer, int length, Pointer<Int8> data) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(data);
|
pointer[i] = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStoreInt64Mint(Pointer<Int64> pointer, int length) {
|
void doStoreInt64Mint(Pointer<Int64> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).store(0x7FFFFFFFFFFFFFFF);
|
pointer[i] = 0x7FFFFFFFFFFFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ void doStoreInt64Mint(Pointer<Int64> pointer, int length) {
|
||||||
int doLoadInt8(Pointer<Int8> pointer, int length) {
|
int doLoadInt8(Pointer<Int8> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ int doLoadInt8(Pointer<Int8> pointer, int length) {
|
||||||
int doLoadUint8(Pointer<Uint8> pointer, int length) {
|
int doLoadUint8(Pointer<Uint8> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ int doLoadUint8(Pointer<Uint8> pointer, int length) {
|
||||||
int doLoadInt16(Pointer<Int16> pointer, int length) {
|
int doLoadInt16(Pointer<Int16> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ int doLoadInt16(Pointer<Int16> pointer, int length) {
|
||||||
int doLoadUint16(Pointer<Uint16> pointer, int length) {
|
int doLoadUint16(Pointer<Uint16> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ int doLoadUint16(Pointer<Uint16> pointer, int length) {
|
||||||
int doLoadInt32(Pointer<Int32> pointer, int length) {
|
int doLoadInt32(Pointer<Int32> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ int doLoadInt32(Pointer<Int32> pointer, int length) {
|
||||||
int doLoadUint32(Pointer<Uint32> pointer, int length) {
|
int doLoadUint32(Pointer<Uint32> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ int doLoadUint32(Pointer<Uint32> pointer, int length) {
|
||||||
int doLoadInt64(Pointer<Int64> pointer, int length) {
|
int doLoadInt64(Pointer<Int64> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ int doLoadInt64(Pointer<Int64> pointer, int length) {
|
||||||
int doLoadUint64(Pointer<Uint64> pointer, int length) {
|
int doLoadUint64(Pointer<Uint64> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ int doLoadUint64(Pointer<Uint64> pointer, int length) {
|
||||||
double doLoadFloat(Pointer<Float> pointer, int length) {
|
double doLoadFloat(Pointer<Float> pointer, int length) {
|
||||||
double x = 0;
|
double x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<double>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ double doLoadFloat(Pointer<Float> pointer, int length) {
|
||||||
double doLoadDouble(Pointer<Double> pointer, int length) {
|
double doLoadDouble(Pointer<Double> pointer, int length) {
|
||||||
double x = 0;
|
double x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<double>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ int doLoadPointer(Pointer<Pointer<Int8>> pointer, int length) {
|
||||||
Pointer<Int8> x;
|
Pointer<Int8> x;
|
||||||
int address_xor = 0;
|
int address_xor = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x = pointer.elementAt(i).load();
|
x = pointer[i];
|
||||||
address_xor ^= x.address;
|
address_xor ^= x.address;
|
||||||
}
|
}
|
||||||
return address_xor;
|
return address_xor;
|
||||||
|
@ -188,7 +188,7 @@ int doLoadPointer(Pointer<Pointer<Int8>> pointer, int length) {
|
||||||
int doLoadInt64Mint(Pointer<Int64> pointer, int length) {
|
int doLoadInt64Mint(Pointer<Int64> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<int>();
|
x += pointer[i];
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import 'package:benchmark_harness/benchmark_harness.dart';
|
||||||
|
|
||||||
void doStoreInt32(Pointer<VeryLargeStruct> pointer, int length) {
|
void doStoreInt32(Pointer<VeryLargeStruct> pointer, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
pointer.elementAt(i).load<VeryLargeStruct>().c = 1;
|
pointer[i].c = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ void doStoreInt32(Pointer<VeryLargeStruct> pointer, int length) {
|
||||||
int doLoadInt32(Pointer<VeryLargeStruct> pointer, int length) {
|
int doLoadInt32(Pointer<VeryLargeStruct> pointer, int length) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
x += pointer.elementAt(i).load<VeryLargeStruct>().c;
|
x += pointer[i].c;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,8 @@ However, before we can write to C memory from dart, we need to `allocate` some m
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
Pointer<Uint8> p = allocate(); // Infers type argument allocate<Uint8>(), and allocates 1 byte.
|
Pointer<Uint8> p = allocate(); // Infers type argument allocate<Uint8>(), and allocates 1 byte.
|
||||||
p.store(123); // Stores a Dart int into this C int8.
|
p.value = 123; // Stores a Dart int into this C int8.
|
||||||
int v = p.load(); // Infers type argument p.load<int>(), and loads a value from C memory.
|
int v = p.value; // Loads a value from C memory.
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that you can only load a Dart `int` from a C `Uint8`.
|
Note that you can only load a Dart `int` from a C `Uint8`.
|
||||||
|
@ -92,10 +92,10 @@ We can do this by using `elementAt`.
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
CString string = allocate(count: 4).cast(); // Allocates 4 bytes and casts it to a string.
|
CString string = allocate(count: 4).cast(); // Allocates 4 bytes and casts it to a string.
|
||||||
string.store(73); // Stores 'F' at index 0.
|
string.value = 73; // Stores 'F' at index 0.
|
||||||
string.elementAt(1).store(73); // Stores 'F' at index 1.
|
string[1] = 73; // Stores 'F' at index 1.
|
||||||
string.elementAt(2).store(70); // Stores 'I' at index 2.
|
string[2] = 70; // Stores 'I' at index 2.
|
||||||
string.elementAt(3).store(0); // Null terminates the string.
|
string[3] = 0; // Null terminates the string.
|
||||||
```
|
```
|
||||||
|
|
||||||
We wrap the above logic of allocating strings in the constructor `CString.allocate`.
|
We wrap the above logic of allocating strings in the constructor `CString.allocate`.
|
||||||
|
@ -113,7 +113,7 @@ With `dart:ffi` we are responsible for freeing C memory that we allocate.
|
||||||
So after calling `sqlite3_prepare_v2` we read out the statement pointer, and free the statement pointer pointer and `CString` which held the query string.
|
So after calling `sqlite3_prepare_v2` we read out the statement pointer, and free the statement pointer pointer and `CString` which held the query string.
|
||||||
|
|
||||||
```
|
```
|
||||||
StatementPointer statement = statementOut.load();
|
StatementPointer statement = statementOut.value;
|
||||||
statementOut.free();
|
statementOut.free();
|
||||||
queryC.free();
|
queryC.free();
|
||||||
```
|
```
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Database {
|
||||||
final pathC = Utf8.allocate(path);
|
final pathC = Utf8.allocate(path);
|
||||||
final int resultCode =
|
final int resultCode =
|
||||||
bindings.sqlite3_open_v2(pathC, dbOut, flags, Pointer.fromAddress(0));
|
bindings.sqlite3_open_v2(pathC, dbOut, flags, Pointer.fromAddress(0));
|
||||||
_database = dbOut.load();
|
_database = dbOut.value;
|
||||||
dbOut.free();
|
dbOut.free();
|
||||||
pathC.free();
|
pathC.free();
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ class Database {
|
||||||
Pointer<Utf8> queryC = Utf8.allocate(query);
|
Pointer<Utf8> queryC = Utf8.allocate(query);
|
||||||
int resultCode = bindings.sqlite3_prepare_v2(
|
int resultCode = bindings.sqlite3_prepare_v2(
|
||||||
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
|
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
|
||||||
Pointer<Statement> statement = statementOut.load();
|
Pointer<Statement> statement = statementOut.value;
|
||||||
statementOut.free();
|
statementOut.free();
|
||||||
queryC.free();
|
queryC.free();
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ class Database {
|
||||||
Pointer<Utf8> queryC = Utf8.allocate(query);
|
Pointer<Utf8> queryC = Utf8.allocate(query);
|
||||||
int resultCode = bindings.sqlite3_prepare_v2(
|
int resultCode = bindings.sqlite3_prepare_v2(
|
||||||
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
|
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
|
||||||
Pointer<Statement> statement = statementOut.load();
|
Pointer<Statement> statement = statementOut.value;
|
||||||
statementOut.free();
|
statementOut.free();
|
||||||
queryC.free();
|
queryC.free();
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ class Database {
|
||||||
int columnCount = bindings.sqlite3_column_count(statement);
|
int columnCount = bindings.sqlite3_column_count(statement);
|
||||||
for (int i = 0; i < columnCount; i++) {
|
for (int i = 0; i < columnCount; i++) {
|
||||||
String columnName =
|
String columnName =
|
||||||
bindings.sqlite3_column_name(statement, i).load<Utf8>().toString();
|
bindings.sqlite3_column_name(statement, i).ref.toString();
|
||||||
columnIndices[columnName] = i;
|
columnIndices[columnName] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,13 +106,12 @@ class Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLiteException _loadError([int errorCode]) {
|
SQLiteException _loadError([int errorCode]) {
|
||||||
String errorMessage =
|
String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString();
|
||||||
bindings.sqlite3_errmsg(_database).load<Utf8>().toString();
|
|
||||||
if (errorCode == null) {
|
if (errorCode == null) {
|
||||||
return SQLiteException(errorMessage);
|
return SQLiteException(errorMessage);
|
||||||
}
|
}
|
||||||
String errorCodeExplanation =
|
String errorCodeExplanation =
|
||||||
bindings.sqlite3_errstr(errorCode).load<Utf8>().toString();
|
bindings.sqlite3_errstr(errorCode).ref.toString();
|
||||||
return SQLiteException(
|
return SQLiteException(
|
||||||
"$errorMessage (Code $errorCode: $errorCodeExplanation)");
|
"$errorMessage (Code $errorCode: $errorCodeExplanation)");
|
||||||
}
|
}
|
||||||
|
@ -214,7 +213,7 @@ class Row {
|
||||||
} else {
|
} else {
|
||||||
dynamicType = _typeFromText(bindings
|
dynamicType = _typeFromText(bindings
|
||||||
.sqlite3_column_decltype(_statement, columnIndex)
|
.sqlite3_column_decltype(_statement, columnIndex)
|
||||||
.load<Utf8>()
|
.ref
|
||||||
.toString());
|
.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,10 +250,7 @@ class Row {
|
||||||
/// Reads column [columnIndex] and converts to [Type.Text] if not text.
|
/// Reads column [columnIndex] and converts to [Type.Text] if not text.
|
||||||
String readColumnByIndexAsText(int columnIndex) {
|
String readColumnByIndexAsText(int columnIndex) {
|
||||||
_checkIsCurrentRow();
|
_checkIsCurrentRow();
|
||||||
return bindings
|
return bindings.sqlite3_column_text(_statement, columnIndex).ref.toString();
|
||||||
.sqlite3_column_text(_statement, columnIndex)
|
|
||||||
.load<Utf8>()
|
|
||||||
.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _checkIsCurrentRow() {
|
void _checkIsCurrentRow() {
|
||||||
|
|
|
@ -29,9 +29,9 @@ class Utf8 extends Struct<Utf8> {
|
||||||
List<int> units = Utf8Encoder().convert(dartStr);
|
List<int> units = Utf8Encoder().convert(dartStr);
|
||||||
Pointer<Utf8> str = Pointer.allocate(count: units.length + 1);
|
Pointer<Utf8> str = Pointer.allocate(count: units.length + 1);
|
||||||
for (int i = 0; i < units.length; ++i) {
|
for (int i = 0; i < units.length; ++i) {
|
||||||
str.elementAt(i).load<Utf8>().char = units[i];
|
str[i].char = units[i];
|
||||||
}
|
}
|
||||||
str.elementAt(units.length).load<Utf8>().char = 0;
|
str[units.length].char = 0;
|
||||||
return str.cast();
|
return str.cast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +40,9 @@ class Utf8 extends Struct<Utf8> {
|
||||||
final str = addressOf;
|
final str = addressOf;
|
||||||
if (str == nullptr) return null;
|
if (str == nullptr) return null;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
while (str.elementAt(++len).load<Utf8>().char != 0);
|
while (str[++len].char != 0);
|
||||||
List<int> units = List(len);
|
List<int> units = List(len);
|
||||||
for (int i = 0; i < len; ++i) units[i] = str.elementAt(i).load<Utf8>().char;
|
for (int i = 0; i < len; ++i) units[i] = str[i].char;
|
||||||
return Utf8Decoder().convert(units);
|
return Utf8Decoder().convert(units);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
// VMOptions=--optimization-counter-threshold=5
|
// VMOptions=--optimization-counter-threshold=5
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
|
||||||
import "package:test/test.dart";
|
import "package:test/test.dart";
|
||||||
|
|
||||||
import '../lib/sqlite.dart';
|
import '../lib/sqlite.dart';
|
||||||
|
@ -11,6 +13,8 @@ import '../lib/src/ffi/utf8.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test("sqlite integration test", () {
|
test("sqlite integration test", () {
|
||||||
|
// TODO(dacoharkes): Put the database relative to this file,
|
||||||
|
// instead of where the script was invoked from.
|
||||||
Database d = Database("test.db");
|
Database d = Database("test.db");
|
||||||
d.execute("drop table if exists Cookies;");
|
d.execute("drop table if exists Cookies;");
|
||||||
d.execute("""
|
d.execute("""
|
||||||
|
@ -165,7 +169,7 @@ void main() {
|
||||||
test("Utf8 unit test", () {
|
test("Utf8 unit test", () {
|
||||||
final String test = 'Hasta Mañana';
|
final String test = 'Hasta Mañana';
|
||||||
final medium = Utf8.allocate(test);
|
final medium = Utf8.allocate(test);
|
||||||
expect(test, medium.load<Utf8>().toString());
|
expect(test, medium.ref.toString());
|
||||||
medium.free();
|
medium.free();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,22 +37,22 @@ void main() {
|
||||||
|
|
||||||
void testNonAlias() {
|
void testNonAlias() {
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
source.store(42);
|
source.value = 42;
|
||||||
final int a = source.load();
|
final int a = source.value;
|
||||||
source.store(1984);
|
source.value = 1984;
|
||||||
// alias.load() should be re-executed, as we wrote to alias.
|
// alias.value should be re-executed, as we wrote to alias.
|
||||||
Expect.notEquals(a, source.load<int>());
|
Expect.notEquals(a, source.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAliasCast() {
|
void testAliasCast() {
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
final alias = source.cast<Int8>().cast<Int64>();
|
final alias = source.cast<Int8>().cast<Int64>();
|
||||||
source.store(42);
|
source.value = 42;
|
||||||
final int a = source.load();
|
final int a = source.value;
|
||||||
alias.store(1984);
|
alias.value = 1984;
|
||||||
// source.load() should be re-executed, we wrote alias which aliases source.
|
// source.value should be re-executed, we wrote alias which aliases source.
|
||||||
Expect.notEquals(a, source.load<int>());
|
Expect.notEquals(a, source.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,22 +60,22 @@ void testAliasCast2() {
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
final alias = source.cast<Int16>().cast<Int64>();
|
final alias = source.cast<Int16>().cast<Int64>();
|
||||||
final alias2 = source.cast<Int8>().cast<Int64>();
|
final alias2 = source.cast<Int8>().cast<Int64>();
|
||||||
alias.store(42);
|
alias.value = 42;
|
||||||
final int a = alias.load();
|
final int a = alias.value;
|
||||||
alias2.store(1984);
|
alias2.value = 1984;
|
||||||
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
|
// alias.value should be re-executed, we wrote alias2 which aliases alias.
|
||||||
Expect.notEquals(a, alias.load<int>());
|
Expect.notEquals(a, alias.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAliasOffsetBy() {
|
void testAliasOffsetBy() {
|
||||||
final source = Pointer<Int64>.allocate(count: 2);
|
final source = Pointer<Int64>.allocate(count: 2);
|
||||||
final alias = source.offsetBy(8).offsetBy(-8);
|
final alias = source.offsetBy(8).offsetBy(-8);
|
||||||
source.store(42);
|
source.value = 42;
|
||||||
final int a = source.load();
|
final int a = source.value;
|
||||||
alias.store(1984);
|
alias.value = 1984;
|
||||||
// source.load() should be re-executed, we wrote alias which aliases source.
|
// source.value should be re-executed, we wrote alias which aliases source.
|
||||||
Expect.notEquals(a, source.load<int>());
|
Expect.notEquals(a, source.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,22 +83,22 @@ void testAliasOffsetBy2() {
|
||||||
final source = Pointer<Int64>.allocate(count: 3);
|
final source = Pointer<Int64>.allocate(count: 3);
|
||||||
final alias = source.offsetBy(16).offsetBy(-16);
|
final alias = source.offsetBy(16).offsetBy(-16);
|
||||||
final alias2 = source.offsetBy(8).offsetBy(-8);
|
final alias2 = source.offsetBy(8).offsetBy(-8);
|
||||||
alias.store(42);
|
alias.value = 42;
|
||||||
final int a = alias.load();
|
final int a = alias.value;
|
||||||
alias2.store(1984);
|
alias2.value = 1984;
|
||||||
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
|
// alias.value should be re-executed, we wrote alias2 which aliases alias.
|
||||||
Expect.notEquals(a, alias.load<int>());
|
Expect.notEquals(a, alias.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAliasElementAt() {
|
void testAliasElementAt() {
|
||||||
final source = Pointer<Int64>.allocate(count: 2);
|
final source = Pointer<Int64>.allocate(count: 2);
|
||||||
final alias = source.elementAt(1).elementAt(-1);
|
final alias = source.elementAt(1).elementAt(-1);
|
||||||
source.store(42);
|
source.value = 42;
|
||||||
final int a = source.load();
|
final int a = source.value;
|
||||||
alias.store(1984);
|
alias.value = 1984;
|
||||||
// source.load() should be re-executed, we wrote alias which aliases source.
|
// source.value should be re-executed, we wrote alias which aliases source.
|
||||||
Expect.notEquals(a, source.load<int>());
|
Expect.notEquals(a, source.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,22 +106,22 @@ void testAliasElementAt2() {
|
||||||
final source = Pointer<Int64>.allocate(count: 3);
|
final source = Pointer<Int64>.allocate(count: 3);
|
||||||
final alias = source.elementAt(2).elementAt(-2);
|
final alias = source.elementAt(2).elementAt(-2);
|
||||||
final alias2 = source.elementAt(1).elementAt(-1);
|
final alias2 = source.elementAt(1).elementAt(-1);
|
||||||
alias.store(42);
|
alias.value = 42;
|
||||||
final int a = alias.load();
|
final int a = alias.value;
|
||||||
alias2.store(1984);
|
alias2.value = 1984;
|
||||||
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
|
// alias.value should be re-executed, we wrote alias2 which aliases alias.
|
||||||
Expect.notEquals(a, alias.load<int>());
|
Expect.notEquals(a, alias.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAliasFromAddress() {
|
void testAliasFromAddress() {
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
final alias = Pointer<Int64>.fromAddress(source.address);
|
final alias = Pointer<Int64>.fromAddress(source.address);
|
||||||
source.store(42);
|
source.value = 42;
|
||||||
final int a = source.load();
|
final int a = source.value;
|
||||||
alias.store(1984);
|
alias.value = 1984;
|
||||||
// source.load() should be re-executed, we wrote alias which aliases source.
|
// source.value should be re-executed, we wrote alias which aliases source.
|
||||||
Expect.notEquals(a, source.load<int>());
|
Expect.notEquals(a, source.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,24 +129,24 @@ void testAliasFromAddress2() {
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
final alias = Pointer<Int64>.fromAddress(source.address);
|
final alias = Pointer<Int64>.fromAddress(source.address);
|
||||||
final alias2 = Pointer<Int64>.fromAddress(source.address);
|
final alias2 = Pointer<Int64>.fromAddress(source.address);
|
||||||
alias.store(42);
|
alias.value = 42;
|
||||||
final int a = alias.load();
|
final int a = alias.value;
|
||||||
alias2.store(1984);
|
alias2.value = 1984;
|
||||||
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
|
// alias.value should be re-executed, we wrote alias2 which aliases alias.
|
||||||
Expect.notEquals(a, alias.load<int>());
|
Expect.notEquals(a, alias.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAliasFromAddressViaMemory() {
|
void testAliasFromAddressViaMemory() {
|
||||||
final helper = Pointer<IntPtr>.allocate();
|
final helper = Pointer<IntPtr>.allocate();
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
helper.store(source.address);
|
helper.value = source.address;
|
||||||
final alias = Pointer<Int64>.fromAddress(helper.load());
|
final alias = Pointer<Int64>.fromAddress(helper.value);
|
||||||
source.store(42);
|
source.value = 42;
|
||||||
final int a = source.load();
|
final int a = source.value;
|
||||||
alias.store(1984);
|
alias.value = 1984;
|
||||||
// source.load() should be re-executed, we wrote alias which aliases source.
|
// source.value should be re-executed, we wrote alias which aliases source.
|
||||||
Expect.notEquals(a, source.load<int>());
|
Expect.notEquals(a, source.value);
|
||||||
helper.free();
|
helper.free();
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
@ -154,14 +154,14 @@ void testAliasFromAddressViaMemory() {
|
||||||
void testAliasFromAddressViaMemory2() {
|
void testAliasFromAddressViaMemory2() {
|
||||||
final helper = Pointer<IntPtr>.allocate();
|
final helper = Pointer<IntPtr>.allocate();
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
helper.store(source.address);
|
helper.value = source.address;
|
||||||
final alias = Pointer<Int64>.fromAddress(helper.load());
|
final alias = Pointer<Int64>.fromAddress(helper.value);
|
||||||
final alias2 = Pointer<Int64>.fromAddress(helper.load());
|
final alias2 = Pointer<Int64>.fromAddress(helper.value);
|
||||||
alias.store(42);
|
alias.value = 42;
|
||||||
final int a = alias.load();
|
final int a = alias.value;
|
||||||
alias2.store(1984);
|
alias2.value = 1984;
|
||||||
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
|
// alias.value should be re-executed, we wrote alias2 which aliases alias.
|
||||||
Expect.notEquals(a, alias.load<int>());
|
Expect.notEquals(a, alias.value);
|
||||||
helper.free();
|
helper.free();
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
@ -178,11 +178,11 @@ void testAliasFromAddressViaNativeFunction() {
|
||||||
final source = Pointer<Int64>.allocate();
|
final source = Pointer<Int64>.allocate();
|
||||||
final alias =
|
final alias =
|
||||||
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
|
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
|
||||||
source.store(42);
|
source.value = 42;
|
||||||
final int a = source.load();
|
final int a = source.value;
|
||||||
alias.store(1984);
|
alias.value = 1984;
|
||||||
// source.load() should be re-executed, we wrote alias which aliases source.
|
// source.value should be re-executed, we wrote alias which aliases source.
|
||||||
Expect.notEquals(a, source.load<int>());
|
Expect.notEquals(a, source.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,11 +192,11 @@ void testAliasFromAddressViaNativeFunction2() {
|
||||||
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
|
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
|
||||||
final alias2 =
|
final alias2 =
|
||||||
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
|
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
|
||||||
alias.store(42);
|
alias.value = 42;
|
||||||
final int a = alias.load();
|
final int a = alias.value;
|
||||||
alias2.store(1984);
|
alias2.value = 1984;
|
||||||
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
|
// alias.value should be re-executed, we wrote alias2 which aliases alias.
|
||||||
Expect.notEquals(a, alias.load<int>());
|
Expect.notEquals(a, alias.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,9 +207,9 @@ Pointer<Int8> makeDerived(Pointer<Int64> source) =>
|
||||||
testPartialOverlap() {
|
testPartialOverlap() {
|
||||||
final source = Pointer<Int64>.allocate(count: 2);
|
final source = Pointer<Int64>.allocate(count: 2);
|
||||||
final derived = makeDerived(source);
|
final derived = makeDerived(source);
|
||||||
source.store(0x1122334455667788);
|
source.value = 0x1122334455667788;
|
||||||
final int value = source.load();
|
final int value = source.value;
|
||||||
derived.store(0xaa);
|
derived.value = 0xaa;
|
||||||
Expect.notEquals(value, source.load<int>());
|
Expect.notEquals(value, source.value);
|
||||||
source.free();
|
source.free();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ class Coordinate extends Struct<Coordinate> {
|
||||||
Pointer<Coordinate> next;
|
Pointer<Coordinate> next;
|
||||||
|
|
||||||
factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
|
factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
|
||||||
return Pointer<Coordinate>.allocate().load<Coordinate>()
|
return Pointer<Coordinate>.allocate().ref
|
||||||
..x = x
|
..x = x
|
||||||
..y = y
|
..y = y
|
||||||
..next = next;
|
..next = next;
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
|
|
||||||
library FfiTest;
|
library FfiTest;
|
||||||
|
|
||||||
import 'dart:ffi' as ffi;
|
import 'dart:ffi';
|
||||||
import 'dart:ffi' show Pointer;
|
|
||||||
|
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
@ -22,16 +21,16 @@ void main() {
|
||||||
void testPointerAllocateTooLarge() {
|
void testPointerAllocateTooLarge() {
|
||||||
// Try to allocate something that doesn't fit in 64 bit address space.
|
// Try to allocate something that doesn't fit in 64 bit address space.
|
||||||
int maxInt = 9223372036854775807; // 2^63 - 1
|
int maxInt = 9223372036854775807; // 2^63 - 1
|
||||||
Expect.throws(() => Pointer<ffi.Int64>.allocate(count: maxInt));
|
Expect.throws(() => Pointer<Int64>.allocate(count: maxInt));
|
||||||
|
|
||||||
// Try to allocate almost the full 64 bit address space.
|
// Try to allocate almost the full 64 bit address space.
|
||||||
int maxInt1_8 = 1152921504606846975; // 2^60 -1
|
int maxInt1_8 = 1152921504606846975; // 2^60 -1
|
||||||
Expect.throws(() => Pointer<ffi.Int64>.allocate(count: maxInt1_8));
|
Expect.throws(() => Pointer<Int64>.allocate(count: maxInt1_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerAllocateNegative() {
|
void testPointerAllocateNegative() {
|
||||||
// Passing in -1 will be converted into an unsigned integer. So, it will try
|
// 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
|
// to allocate SIZE_MAX - 1 + 1 bytes. This will fail as it is the max amount
|
||||||
// of addressable memory on the system.
|
// of addressable memory on the system.
|
||||||
Expect.throws(() => Pointer<ffi.Int8>.allocate(count: -1));
|
Expect.throws(() => Pointer<Int8>.allocate(count: -1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
library FfiTest;
|
library FfiTest;
|
||||||
|
|
||||||
import 'dart:ffi' as ffi;
|
import 'dart:ffi';
|
||||||
import 'dart:ffi' show Pointer;
|
|
||||||
|
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
@ -55,39 +54,39 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerBasic() {
|
void testPointerBasic() {
|
||||||
Pointer<ffi.Int64> p = Pointer.allocate();
|
Pointer<Int64> p = Pointer.allocate();
|
||||||
p.store(42);
|
p.value = 42;
|
||||||
Expect.equals(42, p.load<int>());
|
Expect.equals(42, p.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerFromPointer() {
|
void testPointerFromPointer() {
|
||||||
Pointer<ffi.Int64> p = Pointer.allocate();
|
Pointer<Int64> p = Pointer.allocate();
|
||||||
p.store(1337);
|
p.value = 1337;
|
||||||
int ptr = p.address;
|
int ptr = p.address;
|
||||||
Pointer<ffi.Int64> p2 = Pointer.fromAddress(ptr);
|
Pointer<Int64> p2 = Pointer.fromAddress(ptr);
|
||||||
Expect.equals(1337, p2.load<int>());
|
Expect.equals(1337, p2.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerPointerArithmetic() {
|
void testPointerPointerArithmetic() {
|
||||||
Pointer<ffi.Int64> p = Pointer.allocate(count: 2);
|
Pointer<Int64> p = Pointer.allocate(count: 2);
|
||||||
Pointer<ffi.Int64> p2 = p.elementAt(1);
|
Pointer<Int64> p2 = p.elementAt(1);
|
||||||
p2.store(100);
|
p2.value = 100;
|
||||||
Pointer<ffi.Int64> p3 = p.offsetBy(8);
|
Pointer<Int64> p3 = p.offsetBy(8);
|
||||||
Expect.equals(100, p3.load<int>());
|
Expect.equals(100, p3.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerPointerArithmeticSizes() {
|
void testPointerPointerArithmeticSizes() {
|
||||||
Pointer<ffi.Int64> p = Pointer.allocate(count: 2);
|
Pointer<Int64> p = Pointer.allocate(count: 2);
|
||||||
Pointer<ffi.Int64> p2 = p.elementAt(1);
|
Pointer<Int64> p2 = p.elementAt(1);
|
||||||
int addr = p.address;
|
int addr = p.address;
|
||||||
Expect.equals(addr + 8, p2.address);
|
Expect.equals(addr + 8, p2.address);
|
||||||
p.free();
|
p.free();
|
||||||
|
|
||||||
Pointer<ffi.Int32> p3 = Pointer.allocate(count: 2);
|
Pointer<Int32> p3 = Pointer.allocate(count: 2);
|
||||||
Pointer<ffi.Int32> p4 = p3.elementAt(1);
|
Pointer<Int32> p4 = p3.elementAt(1);
|
||||||
addr = p3.address;
|
addr = p3.address;
|
||||||
Expect.equals(addr + 4, p4.address);
|
Expect.equals(addr + 4, p4.address);
|
||||||
p3.free();
|
p3.free();
|
||||||
|
@ -100,9 +99,9 @@ void testPointerAllocateZero() {
|
||||||
//
|
//
|
||||||
// Null pointer throws a Dart exception.
|
// Null pointer throws a Dart exception.
|
||||||
bool returnedNullPointer = false;
|
bool returnedNullPointer = false;
|
||||||
ffi.Pointer<ffi.Int8> p;
|
Pointer<Int8> p;
|
||||||
try {
|
try {
|
||||||
p = Pointer<ffi.Int8>.allocate(count: 0);
|
p = Pointer<Int8>.allocate(count: 0);
|
||||||
} on Exception {
|
} on Exception {
|
||||||
returnedNullPointer = true;
|
returnedNullPointer = true;
|
||||||
}
|
}
|
||||||
|
@ -112,289 +111,286 @@ void testPointerAllocateZero() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerCast() {
|
void testPointerCast() {
|
||||||
Pointer<ffi.Int64> p = Pointer.allocate();
|
Pointer<Int64> p = Pointer.allocate();
|
||||||
Pointer<ffi.Int32> p2 = p.cast(); // gets the correct type args back
|
Pointer<Int32> p2 = p.cast(); // gets the correct type args back
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCastGeneric() {
|
void testCastGeneric() {
|
||||||
Pointer<T> generic<T extends ffi.NativeType>(Pointer<ffi.Int16> p) {
|
Pointer<T> generic<T extends NativeType>(Pointer<Int16> p) {
|
||||||
return p.cast();
|
return p.cast();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer<ffi.Int16> p = Pointer.allocate();
|
Pointer<Int16> p = Pointer.allocate();
|
||||||
Pointer<ffi.Int64> p2 = generic(p);
|
Pointer<Int64> p2 = generic(p);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCastGeneric2() {
|
void testCastGeneric2() {
|
||||||
Pointer<ffi.Int64> generic<T extends ffi.NativeType>(Pointer<T> p) {
|
Pointer<Int64> generic<T extends NativeType>(Pointer<T> p) {
|
||||||
return p.cast();
|
return p.cast();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer<ffi.Int16> p = Pointer.allocate();
|
Pointer<Int16> p = Pointer.allocate();
|
||||||
Pointer<ffi.Int64> p2 = generic(p);
|
Pointer<Int64> p2 = generic(p);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCastNativeType() {
|
void testCastNativeType() {
|
||||||
ffi.Pointer<ffi.Int64> p = Pointer.allocate();
|
Pointer<Int64> p = Pointer.allocate();
|
||||||
p.cast<ffi.Pointer>();
|
p.cast<Pointer>();
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCondensedNumbersInt8() {
|
void testCondensedNumbersInt8() {
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.allocate(count: 8);
|
Pointer<Int8> p = Pointer.allocate(count: 8);
|
||||||
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
||||||
p.elementAt(i).store(i * 3);
|
p[i] = i * 3;
|
||||||
}
|
}
|
||||||
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
||||||
Expect.equals(i * 3, p.elementAt(i).load<int>());
|
Expect.equals(i * 3, p[i]);
|
||||||
}
|
}
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCondensedNumbersFloat() {
|
void testCondensedNumbersFloat() {
|
||||||
ffi.Pointer<ffi.Float> p = Pointer.allocate(count: 8);
|
Pointer<Float> p = Pointer.allocate(count: 8);
|
||||||
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
||||||
p.elementAt(i).store(1.511366173271439e-13);
|
p[i] = 1.511366173271439e-13;
|
||||||
}
|
}
|
||||||
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
|
||||||
Expect.equals(1.511366173271439e-13, p.elementAt(i).load<double>());
|
Expect.equals(1.511366173271439e-13, p[i]);
|
||||||
}
|
}
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeInt8() {
|
void testRangeInt8() {
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
Pointer<Int8> p = Pointer.allocate();
|
||||||
p.store(127);
|
p.value = 127;
|
||||||
Expect.equals(127, p.load<int>());
|
Expect.equals(127, p.value);
|
||||||
p.store(-128);
|
p.value = -128;
|
||||||
Expect.equals(-128, p.load<int>());
|
Expect.equals(-128, p.value);
|
||||||
|
|
||||||
Expect.equals(0x0000000000000080, 128);
|
Expect.equals(0x0000000000000080, 128);
|
||||||
Expect.equals(0xFFFFFFFFFFFFFF80, -128);
|
Expect.equals(0xFFFFFFFFFFFFFF80, -128);
|
||||||
p.store(128);
|
p.value = 128;
|
||||||
Expect.equals(-128, p.load<int>()); // truncated and sign extended
|
Expect.equals(-128, p.value); // truncated and sign extended
|
||||||
|
|
||||||
Expect.equals(0xFFFFFFFFFFFFFF7F, -129);
|
Expect.equals(0xFFFFFFFFFFFFFF7F, -129);
|
||||||
Expect.equals(0x000000000000007F, 127);
|
Expect.equals(0x000000000000007F, 127);
|
||||||
p.store(-129);
|
p.value = -129;
|
||||||
Expect.equals(127, p.load<int>()); // truncated
|
Expect.equals(127, p.value); // truncated
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeUint8() {
|
void testRangeUint8() {
|
||||||
ffi.Pointer<ffi.Uint8> p = Pointer.allocate();
|
Pointer<Uint8> p = Pointer.allocate();
|
||||||
p.store(255);
|
p.value = 255;
|
||||||
Expect.equals(255, p.load<int>());
|
Expect.equals(255, p.value);
|
||||||
p.store(0);
|
p.value = 0;
|
||||||
Expect.equals(0, p.load<int>());
|
Expect.equals(0, p.value);
|
||||||
|
|
||||||
Expect.equals(0x0000000000000000, 0);
|
Expect.equals(0x0000000000000000, 0);
|
||||||
Expect.equals(0x0000000000000100, 256);
|
Expect.equals(0x0000000000000100, 256);
|
||||||
p.store(256);
|
p.value = 256;
|
||||||
Expect.equals(0, p.load<int>()); // truncated
|
Expect.equals(0, p.value); // truncated
|
||||||
|
|
||||||
Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
|
Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
|
||||||
Expect.equals(0x00000000000000FF, 255);
|
Expect.equals(0x00000000000000FF, 255);
|
||||||
p.store(-1);
|
p.value = -1;
|
||||||
Expect.equals(255, p.load<int>()); // truncated
|
Expect.equals(255, p.value); // truncated
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeInt16() {
|
void testRangeInt16() {
|
||||||
ffi.Pointer<ffi.Int16> p = Pointer.allocate();
|
Pointer<Int16> p = Pointer.allocate();
|
||||||
p.store(0x7FFF);
|
p.value = 0x7FFF;
|
||||||
Expect.equals(0x7FFF, p.load<int>());
|
Expect.equals(0x7FFF, p.value);
|
||||||
p.store(-0x8000);
|
p.value = -0x8000;
|
||||||
Expect.equals(-0x8000, p.load<int>());
|
Expect.equals(-0x8000, p.value);
|
||||||
p.store(0x8000);
|
p.value = 0x8000;
|
||||||
Expect.equals(
|
Expect.equals(0xFFFFFFFFFFFF8000, p.value); // truncated and sign extended
|
||||||
0xFFFFFFFFFFFF8000, p.load<int>()); // truncated and sign extended
|
p.value = -0x8001;
|
||||||
p.store(-0x8001);
|
Expect.equals(0x7FFF, p.value); // truncated
|
||||||
Expect.equals(0x7FFF, p.load<int>()); // truncated
|
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeUint16() {
|
void testRangeUint16() {
|
||||||
ffi.Pointer<ffi.Uint16> p = Pointer.allocate();
|
Pointer<Uint16> p = Pointer.allocate();
|
||||||
p.store(0xFFFF);
|
p.value = 0xFFFF;
|
||||||
Expect.equals(0xFFFF, p.load<int>());
|
Expect.equals(0xFFFF, p.value);
|
||||||
p.store(0);
|
p.value = 0;
|
||||||
Expect.equals(0, p.load<int>());
|
Expect.equals(0, p.value);
|
||||||
p.store(0x10000);
|
p.value = 0x10000;
|
||||||
Expect.equals(0, p.load<int>()); // truncated
|
Expect.equals(0, p.value); // truncated
|
||||||
p.store(-1);
|
p.value = -1;
|
||||||
Expect.equals(0xFFFF, p.load<int>()); // truncated
|
Expect.equals(0xFFFF, p.value); // truncated
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeInt32() {
|
void testRangeInt32() {
|
||||||
ffi.Pointer<ffi.Int32> p = Pointer.allocate();
|
Pointer<Int32> p = Pointer.allocate();
|
||||||
p.store(0x7FFFFFFF);
|
p.value = 0x7FFFFFFF;
|
||||||
Expect.equals(0x7FFFFFFF, p.load<int>());
|
Expect.equals(0x7FFFFFFF, p.value);
|
||||||
p.store(-0x80000000);
|
p.value = -0x80000000;
|
||||||
Expect.equals(-0x80000000, p.load<int>());
|
Expect.equals(-0x80000000, p.value);
|
||||||
p.store(0x80000000);
|
p.value = 0x80000000;
|
||||||
Expect.equals(
|
Expect.equals(0xFFFFFFFF80000000, p.value); // truncated and sign extended
|
||||||
0xFFFFFFFF80000000, p.load<int>()); // truncated and sign extended
|
p.value = -0x80000001;
|
||||||
p.store(-0x80000001);
|
Expect.equals(0x7FFFFFFF, p.value); // truncated
|
||||||
Expect.equals(0x7FFFFFFF, p.load<int>()); // truncated
|
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeUint32() {
|
void testRangeUint32() {
|
||||||
ffi.Pointer<ffi.Uint32> p = Pointer.allocate();
|
Pointer<Uint32> p = Pointer.allocate();
|
||||||
p.store(0xFFFFFFFF);
|
p.value = 0xFFFFFFFF;
|
||||||
Expect.equals(0xFFFFFFFF, p.load<int>());
|
Expect.equals(0xFFFFFFFF, p.value);
|
||||||
p.store(0);
|
p.value = 0;
|
||||||
Expect.equals(0, p.load<int>());
|
Expect.equals(0, p.value);
|
||||||
p.store(0x100000000);
|
p.value = 0x100000000;
|
||||||
Expect.equals(0, p.load<int>()); // truncated
|
Expect.equals(0, p.value); // truncated
|
||||||
p.store(-1);
|
p.value = -1;
|
||||||
Expect.equals(0xFFFFFFFF, p.load<int>()); // truncated
|
Expect.equals(0xFFFFFFFF, p.value); // truncated
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeInt64() {
|
void testRangeInt64() {
|
||||||
ffi.Pointer<ffi.Int64> p = Pointer.allocate();
|
Pointer<Int64> p = Pointer.allocate();
|
||||||
p.store(0x7FFFFFFFFFFFFFFF); // 2 ^ 63 - 1
|
p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
|
||||||
Expect.equals(0x7FFFFFFFFFFFFFFF, p.load<int>());
|
Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
|
||||||
p.store(-0x8000000000000000); // -2 ^ 63
|
p.value = -0x8000000000000000; // -2 ^ 63
|
||||||
Expect.equals(-0x8000000000000000, p.load<int>());
|
Expect.equals(-0x8000000000000000, p.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeUint64() {
|
void testRangeUint64() {
|
||||||
ffi.Pointer<ffi.Uint64> p = Pointer.allocate();
|
Pointer<Uint64> p = Pointer.allocate();
|
||||||
p.store(0x7FFFFFFFFFFFFFFF); // 2 ^ 63 - 1
|
p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
|
||||||
Expect.equals(0x7FFFFFFFFFFFFFFF, p.load<int>());
|
Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
|
||||||
p.store(-0x8000000000000000); // -2 ^ 63 interpreted as 2 ^ 63
|
p.value = -0x8000000000000000; // -2 ^ 63 interpreted as 2 ^ 63
|
||||||
Expect.equals(-0x8000000000000000, p.load<int>());
|
Expect.equals(-0x8000000000000000, p.value);
|
||||||
|
|
||||||
// Dart allows interpreting bits both signed and unsigned
|
// Dart allows interpreting bits both signed and unsigned
|
||||||
Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
|
Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
|
||||||
p.store(-1); // -1 interpreted as 2 ^ 64 - 1
|
p.value = -1; // -1 interpreted as 2 ^ 64 - 1
|
||||||
Expect.equals(-1, p.load<int>());
|
Expect.equals(-1, p.value);
|
||||||
Expect.equals(0xFFFFFFFFFFFFFFFF, p.load<int>());
|
Expect.equals(0xFFFFFFFFFFFFFFFF, p.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRangeIntPtr() {
|
void testRangeIntPtr() {
|
||||||
ffi.Pointer<ffi.IntPtr> p = Pointer.allocate();
|
Pointer<IntPtr> p = Pointer.allocate();
|
||||||
int pAddr = p.address;
|
int pAddr = p.address;
|
||||||
p.store(pAddr); // its own address should fit
|
p.value = pAddr; // its own address should fit
|
||||||
p.store(0x7FFFFFFF); // and 32 bit addresses should fit
|
p.value = 0x7FFFFFFF; // and 32 bit addresses should fit
|
||||||
Expect.equals(0x7FFFFFFF, p.load<int>());
|
Expect.equals(0x7FFFFFFF, p.value);
|
||||||
p.store(-0x80000000);
|
p.value = -0x80000000;
|
||||||
Expect.equals(-0x80000000, p.load<int>());
|
Expect.equals(-0x80000000, p.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFloat() {
|
void testFloat() {
|
||||||
ffi.Pointer<ffi.Float> p = Pointer.allocate();
|
Pointer<Float> p = Pointer.allocate();
|
||||||
p.store(1.511366173271439e-13);
|
p.value = 1.511366173271439e-13;
|
||||||
Expect.equals(1.511366173271439e-13, p.load<double>());
|
Expect.equals(1.511366173271439e-13, p.value);
|
||||||
p.store(1.4260258159703532e-105); // float does not have enough precision
|
p.value = 1.4260258159703532e-105; // float does not have enough precision
|
||||||
Expect.notEquals(1.4260258159703532e-105, p.load<double>());
|
Expect.notEquals(1.4260258159703532e-105, p.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDouble() {
|
void testDouble() {
|
||||||
ffi.Pointer<ffi.Double> p = Pointer.allocate();
|
Pointer<Double> p = Pointer.allocate();
|
||||||
p.store(1.4260258159703532e-105);
|
p.value = 1.4260258159703532e-105;
|
||||||
Expect.equals(1.4260258159703532e-105, p.load<double>());
|
Expect.equals(1.4260258159703532e-105, p.value);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testVoid() {
|
void testVoid() {
|
||||||
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
|
Pointer<IntPtr> p1 = Pointer.allocate();
|
||||||
ffi.Pointer<ffi.Void> p2 = p1.cast(); // make this dart pointer opaque
|
Pointer<Void> p2 = p1.cast(); // make this dart pointer opaque
|
||||||
p2.address; // we can print the address
|
p2.address; // we can print the address
|
||||||
p2.free();
|
p2.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerPointer() {
|
void testPointerPointer() {
|
||||||
ffi.Pointer<ffi.Int16> p = Pointer.allocate();
|
Pointer<Int16> p = Pointer.allocate();
|
||||||
p.store(17);
|
p.value = 17;
|
||||||
ffi.Pointer<ffi.Pointer<ffi.Int16>> p2 = Pointer.allocate();
|
Pointer<Pointer<Int16>> p2 = Pointer.allocate();
|
||||||
p2.store(p);
|
p2.value = p;
|
||||||
Expect.equals(17, p2.load<ffi.Pointer<ffi.Int16>>().load<int>());
|
Expect.equals(17, p2.value.value);
|
||||||
p2.free();
|
p2.free();
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerPointerNull() {
|
void testPointerPointerNull() {
|
||||||
Pointer<Pointer<ffi.Int8>> pointerToPointer = Pointer.allocate();
|
Pointer<Pointer<Int8>> pointerToPointer = Pointer.allocate();
|
||||||
Pointer<ffi.Int8> value = ffi.nullptr.cast();
|
Pointer<Int8> value = nullptr.cast();
|
||||||
pointerToPointer.store(value);
|
pointerToPointer.value = value;
|
||||||
value = pointerToPointer.load();
|
value = pointerToPointer.value;
|
||||||
Expect.equals(value, ffi.nullptr);
|
Expect.equals(value, nullptr);
|
||||||
value = Pointer.allocate();
|
value = Pointer.allocate();
|
||||||
pointerToPointer.store(value);
|
pointerToPointer.value = value;
|
||||||
value = pointerToPointer.load();
|
value = pointerToPointer.value;
|
||||||
Expect.isNotNull(value);
|
Expect.isNotNull(value);
|
||||||
value.free();
|
value.free();
|
||||||
value = ffi.nullptr.cast();
|
value = nullptr.cast();
|
||||||
pointerToPointer.store(value);
|
pointerToPointer.value = value;
|
||||||
value = pointerToPointer.load();
|
value = pointerToPointer.value;
|
||||||
Expect.equals(value, ffi.nullptr);
|
Expect.equals(value, nullptr);
|
||||||
pointerToPointer.free();
|
pointerToPointer.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointerStoreNull() {
|
void testPointerStoreNull() {
|
||||||
int i = null;
|
int i = null;
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
Pointer<Int8> p = Pointer.allocate();
|
||||||
Expect.throws(() => p.store(i));
|
Expect.throws(() => p.value = i);
|
||||||
p.free();
|
p.free();
|
||||||
double d = null;
|
double d = null;
|
||||||
ffi.Pointer<ffi.Float> p2 = Pointer.allocate();
|
Pointer<Float> p2 = Pointer.allocate();
|
||||||
Expect.throws(() => p2.store(d));
|
Expect.throws(() => p2.value = d);
|
||||||
p2.free();
|
p2.free();
|
||||||
Pointer<ffi.Void> x = null;
|
Pointer<Void> x = null;
|
||||||
ffi.Pointer<ffi.Pointer<ffi.Void>> p3 = Pointer.allocate();
|
Pointer<Pointer<Void>> p3 = Pointer.allocate();
|
||||||
Expect.throws(() => p3.store(x));
|
Expect.throws(() => p3.value = x);
|
||||||
p3.free();
|
p3.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSizeOf() {
|
void testSizeOf() {
|
||||||
Expect.equals(1, ffi.sizeOf<ffi.Int8>());
|
Expect.equals(1, sizeOf<Int8>());
|
||||||
Expect.equals(2, ffi.sizeOf<ffi.Int16>());
|
Expect.equals(2, sizeOf<Int16>());
|
||||||
Expect.equals(4, ffi.sizeOf<ffi.Int32>());
|
Expect.equals(4, sizeOf<Int32>());
|
||||||
Expect.equals(8, ffi.sizeOf<ffi.Int64>());
|
Expect.equals(8, sizeOf<Int64>());
|
||||||
Expect.equals(1, ffi.sizeOf<ffi.Uint8>());
|
Expect.equals(1, sizeOf<Uint8>());
|
||||||
Expect.equals(2, ffi.sizeOf<ffi.Uint16>());
|
Expect.equals(2, sizeOf<Uint16>());
|
||||||
Expect.equals(4, ffi.sizeOf<ffi.Uint32>());
|
Expect.equals(4, sizeOf<Uint32>());
|
||||||
Expect.equals(8, ffi.sizeOf<ffi.Uint64>());
|
Expect.equals(8, sizeOf<Uint64>());
|
||||||
Expect.equals(
|
Expect.equals(true, 4 == sizeOf<IntPtr>() || 8 == sizeOf<IntPtr>());
|
||||||
true, 4 == ffi.sizeOf<ffi.IntPtr>() || 8 == ffi.sizeOf<ffi.IntPtr>());
|
Expect.equals(4, sizeOf<Float>());
|
||||||
Expect.equals(4, ffi.sizeOf<ffi.Float>());
|
Expect.equals(8, sizeOf<Double>());
|
||||||
Expect.equals(8, ffi.sizeOf<ffi.Double>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: stack overflows at around 15k calls
|
// note: stack overflows at around 15k calls
|
||||||
void testPointerChain(int length) {
|
void testPointerChain(int length) {
|
||||||
void createChain(ffi.Pointer<ffi.IntPtr> head, int length, int value) {
|
void createChain(Pointer<IntPtr> head, int length, int value) {
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
head.store(value);
|
head.value = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ffi.Pointer<ffi.IntPtr> next = Pointer.allocate();
|
Pointer<IntPtr> next = Pointer.allocate();
|
||||||
head.store(next.address);
|
head.value = next.address;
|
||||||
createChain(next, length - 1, value);
|
createChain(next, length - 1, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getChainValue(ffi.Pointer<ffi.IntPtr> head, int length) {
|
int getChainValue(Pointer<IntPtr> head, int length) {
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return head.load();
|
return head.value;
|
||||||
}
|
}
|
||||||
ffi.Pointer<ffi.IntPtr> next = Pointer.fromAddress(head.load());
|
Pointer<IntPtr> next = Pointer.fromAddress(head.value);
|
||||||
return getChainValue(next, length - 1);
|
return getChainValue(next, length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeChain(ffi.Pointer<ffi.IntPtr> head, int length) {
|
void freeChain(Pointer<IntPtr> head, int length) {
|
||||||
ffi.Pointer<ffi.IntPtr> next = Pointer.fromAddress(head.load());
|
Pointer<IntPtr> next = Pointer.fromAddress(head.value);
|
||||||
head.free();
|
head.free();
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -402,7 +398,7 @@ void testPointerChain(int length) {
|
||||||
freeChain(next, length - 1);
|
freeChain(next, length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi.Pointer<ffi.IntPtr> head = Pointer.allocate();
|
Pointer<IntPtr> head = Pointer.allocate();
|
||||||
createChain(head, length, 512);
|
createChain(head, length, 512);
|
||||||
int tailValue = getChainValue(head, length);
|
int tailValue = getChainValue(head, length);
|
||||||
Expect.equals(512, tailValue);
|
Expect.equals(512, tailValue);
|
||||||
|
@ -410,56 +406,56 @@ void testPointerChain(int length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testTypeTest() {
|
void testTypeTest() {
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
Pointer<Int8> p = Pointer.allocate();
|
||||||
Expect.isTrue(p is ffi.Pointer);
|
Expect.isTrue(p is Pointer);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testToString() {
|
void testToString() {
|
||||||
ffi.Pointer<ffi.Int16> p = Pointer.allocate();
|
Pointer<Int16> p = Pointer.allocate();
|
||||||
Expect.stringEquals(
|
Expect.stringEquals(
|
||||||
"Pointer<Int16>: address=0x", p.toString().substring(0, 26));
|
"Pointer<Int16>: address=0x", p.toString().substring(0, 26));
|
||||||
p.free();
|
p.free();
|
||||||
ffi.Pointer<ffi.Int64> p2 = Pointer.fromAddress(0x123abc);
|
Pointer<Int64> p2 = Pointer.fromAddress(0x123abc);
|
||||||
Expect.stringEquals("Pointer<Int64>: address=0x123abc", p2.toString());
|
Expect.stringEquals("Pointer<Int64>: address=0x123abc", p2.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testEquality() {
|
void testEquality() {
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.fromAddress(12345678);
|
Pointer<Int8> p = Pointer.fromAddress(12345678);
|
||||||
ffi.Pointer<ffi.Int8> p2 = Pointer.fromAddress(12345678);
|
Pointer<Int8> p2 = Pointer.fromAddress(12345678);
|
||||||
Expect.equals(p, p2);
|
Expect.equals(p, p2);
|
||||||
Expect.equals(p.hashCode, p2.hashCode);
|
Expect.equals(p.hashCode, p2.hashCode);
|
||||||
ffi.Pointer<ffi.Int16> p3 = p.cast();
|
Pointer<Int16> p3 = p.cast();
|
||||||
Expect.equals(p, p3);
|
Expect.equals(p, p3);
|
||||||
Expect.equals(p.hashCode, p3.hashCode);
|
Expect.equals(p.hashCode, p3.hashCode);
|
||||||
Expect.notEquals(p, null);
|
Expect.notEquals(p, null);
|
||||||
Expect.notEquals(null, p);
|
Expect.notEquals(null, p);
|
||||||
ffi.Pointer<ffi.Int8> p4 = p.offsetBy(1337);
|
Pointer<Int8> p4 = p.offsetBy(1337);
|
||||||
Expect.notEquals(p, p4);
|
Expect.notEquals(p, p4);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Int8UnOp = ffi.Int8 Function(ffi.Int8);
|
typedef Int8UnOp = Int8 Function(Int8);
|
||||||
|
|
||||||
void testAllocateGeneric() {
|
void testAllocateGeneric() {
|
||||||
ffi.Pointer<T> generic<T extends ffi.NativeType>() {
|
Pointer<T> generic<T extends NativeType>() {
|
||||||
ffi.Pointer<T> pointer;
|
Pointer<T> pointer;
|
||||||
pointer = Pointer.allocate();
|
pointer = Pointer.allocate();
|
||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi.Pointer p = generic<ffi.Int64>();
|
Pointer p = generic<Int64>();
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAllocateVoid() {
|
void testAllocateVoid() {
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
ffi.Pointer<ffi.Void> p = Pointer.allocate();
|
Pointer<Void> p = Pointer.allocate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAllocateNativeFunction() {
|
void testAllocateNativeFunction() {
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.allocate();
|
Pointer<NativeFunction<Int8UnOp>> p = Pointer.allocate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,42 +466,42 @@ void testAllocateNativeType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSizeOfGeneric() {
|
void testSizeOfGeneric() {
|
||||||
int generic<T extends ffi.Pointer>() {
|
int generic<T extends Pointer>() {
|
||||||
int size;
|
int size;
|
||||||
size = ffi.sizeOf<T>();
|
size = sizeOf<T>();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = generic<ffi.Pointer<ffi.Int64>>();
|
int size = generic<Pointer<Int64>>();
|
||||||
Expect.isTrue(size == 8 || size == 4);
|
Expect.isTrue(size == 8 || size == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSizeOfVoid() {
|
void testSizeOfVoid() {
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
ffi.sizeOf<ffi.Void>();
|
sizeOf<Void>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSizeOfNativeFunction() {
|
void testSizeOfNativeFunction() {
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
ffi.sizeOf<ffi.NativeFunction<Int8UnOp>>();
|
sizeOf<NativeFunction<Int8UnOp>>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSizeOfNativeType() {
|
void testSizeOfNativeType() {
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
ffi.sizeOf();
|
sizeOf();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDynamicInvocation() {
|
void testDynamicInvocation() {
|
||||||
dynamic p = Pointer<ffi.Int8>.allocate();
|
dynamic p = Pointer<Int8>.allocate();
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
final int i = p.load();
|
final int i = p.value;
|
||||||
});
|
});
|
||||||
Expect.throws(() => p.store(1));
|
Expect.throws(() => p.value = 1);
|
||||||
p.elementAt(5); // Works, but is slow.
|
p.elementAt(5); // Works, but is slow.
|
||||||
final int addr = p.address;
|
final int addr = p.address;
|
||||||
final Pointer<ffi.Int16> p2 = p.cast<ffi.Int16>();
|
final Pointer<Int16> p2 = p.cast<Int16>();
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ main() {
|
||||||
void testInt8Load() {
|
void testInt8Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Int8> ptr = Pointer.allocate();
|
Pointer<Int8> ptr = Pointer.allocate();
|
||||||
ptr.store(0xff);
|
ptr.value = 0xff;
|
||||||
Int8List list = ptr.asExternalTypedData();
|
Int8List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], -1);
|
Expect.equals(list[0], -1);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -55,14 +55,14 @@ void testInt8Store() {
|
||||||
Int8List list = ptr.asExternalTypedData();
|
Int8List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xff;
|
list[0] = 0xff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), -1);
|
Expect.equals(ptr.value, -1);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testUint8Load() {
|
void testUint8Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Uint8> ptr = Pointer.allocate();
|
Pointer<Uint8> ptr = Pointer.allocate();
|
||||||
ptr.store(0xff);
|
ptr.value = 0xff;
|
||||||
Uint8List list = ptr.asExternalTypedData();
|
Uint8List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], 0xff);
|
Expect.equals(list[0], 0xff);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -75,14 +75,14 @@ void testUint8Store() {
|
||||||
Uint8List list = ptr.asExternalTypedData();
|
Uint8List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xff;
|
list[0] = 0xff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), 0xff);
|
Expect.equals(ptr.value, 0xff);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testInt16Load() {
|
void testInt16Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Int16> ptr = Pointer.allocate();
|
Pointer<Int16> ptr = Pointer.allocate();
|
||||||
ptr.store(0xffff);
|
ptr.value = 0xffff;
|
||||||
Int16List list = ptr.asExternalTypedData();
|
Int16List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], -1);
|
Expect.equals(list[0], -1);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -95,14 +95,14 @@ void testInt16Store() {
|
||||||
Int16List list = ptr.asExternalTypedData();
|
Int16List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xffff;
|
list[0] = 0xffff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), -1);
|
Expect.equals(ptr.value, -1);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testUint16Load() {
|
void testUint16Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Uint16> ptr = Pointer.allocate();
|
Pointer<Uint16> ptr = Pointer.allocate();
|
||||||
ptr.store(0xffff);
|
ptr.value = 0xffff;
|
||||||
Uint16List list = ptr.asExternalTypedData();
|
Uint16List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], 0xffff);
|
Expect.equals(list[0], 0xffff);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -115,14 +115,14 @@ void testUint16Store() {
|
||||||
Uint16List list = ptr.asExternalTypedData();
|
Uint16List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xffff;
|
list[0] = 0xffff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), 0xffff);
|
Expect.equals(ptr.value, 0xffff);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testInt32Load() {
|
void testInt32Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Int32> ptr = Pointer.allocate();
|
Pointer<Int32> ptr = Pointer.allocate();
|
||||||
ptr.store(0xffffffff);
|
ptr.value = 0xffffffff;
|
||||||
Int32List list = ptr.asExternalTypedData();
|
Int32List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], -1);
|
Expect.equals(list[0], -1);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -135,14 +135,14 @@ void testInt32Store() {
|
||||||
Int32List list = ptr.asExternalTypedData();
|
Int32List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xffffffff;
|
list[0] = 0xffffffff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), -1);
|
Expect.equals(ptr.value, -1);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testUint32Load() {
|
void testUint32Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Uint32> ptr = Pointer.allocate();
|
Pointer<Uint32> ptr = Pointer.allocate();
|
||||||
ptr.store(0xffffffff);
|
ptr.value = 0xffffffff;
|
||||||
Uint32List list = ptr.asExternalTypedData();
|
Uint32List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], 0xffffffff);
|
Expect.equals(list[0], 0xffffffff);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -155,14 +155,14 @@ void testUint32Store() {
|
||||||
Uint32List list = ptr.asExternalTypedData();
|
Uint32List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xffffffff;
|
list[0] = 0xffffffff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), 0xffffffff);
|
Expect.equals(ptr.value, 0xffffffff);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testInt64Load() {
|
void testInt64Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Int64> ptr = Pointer.allocate();
|
Pointer<Int64> ptr = Pointer.allocate();
|
||||||
ptr.store(0xffffffffffffffff);
|
ptr.value = 0xffffffffffffffff;
|
||||||
Int64List list = ptr.asExternalTypedData();
|
Int64List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], -1);
|
Expect.equals(list[0], -1);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -175,14 +175,14 @@ void testInt64Store() {
|
||||||
Int64List list = ptr.asExternalTypedData();
|
Int64List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xffffffffffffffff;
|
list[0] = 0xffffffffffffffff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), -1);
|
Expect.equals(ptr.value, -1);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testUint64Load() {
|
void testUint64Load() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Uint64> ptr = Pointer.allocate();
|
Pointer<Uint64> ptr = Pointer.allocate();
|
||||||
ptr.store(0xffffffffffffffff);
|
ptr.value = 0xffffffffffffffff;
|
||||||
Uint64List list = ptr.asExternalTypedData();
|
Uint64List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], 0xffffffffffffffff);
|
Expect.equals(list[0], 0xffffffffffffffff);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -195,7 +195,7 @@ void testUint64Store() {
|
||||||
Uint64List list = ptr.asExternalTypedData();
|
Uint64List list = ptr.asExternalTypedData();
|
||||||
list[0] = 0xffffffffffffffff;
|
list[0] = 0xffffffffffffffff;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<int>(), 0xffffffffffffffff);
|
Expect.equals(ptr.value, 0xffffffffffffffff);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ double maxDouble = (2 - pow(2, -52)) * pow(2, pow(2, 10) - 1);
|
||||||
void testFloatLoad() {
|
void testFloatLoad() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Float> ptr = Pointer.allocate();
|
Pointer<Float> ptr = Pointer.allocate();
|
||||||
ptr.store(maxFloat);
|
ptr.value = maxFloat;
|
||||||
Float32List list = ptr.asExternalTypedData();
|
Float32List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], maxFloat);
|
Expect.equals(list[0], maxFloat);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -230,14 +230,14 @@ void testFloatStore() {
|
||||||
Float32List list = ptr.asExternalTypedData();
|
Float32List list = ptr.asExternalTypedData();
|
||||||
list[0] = maxFloat;
|
list[0] = maxFloat;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<double>(), maxFloat);
|
Expect.equals(ptr.value, maxFloat);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDoubleLoad() {
|
void testDoubleLoad() {
|
||||||
// Load
|
// Load
|
||||||
Pointer<Double> ptr = Pointer.allocate();
|
Pointer<Double> ptr = Pointer.allocate();
|
||||||
ptr.store(maxDouble);
|
ptr.value = maxDouble;
|
||||||
Float64List list = ptr.asExternalTypedData();
|
Float64List list = ptr.asExternalTypedData();
|
||||||
Expect.equals(list[0], maxDouble);
|
Expect.equals(list[0], maxDouble);
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
|
@ -250,7 +250,7 @@ void testDoubleStore() {
|
||||||
Float64List list = ptr.asExternalTypedData();
|
Float64List list = ptr.asExternalTypedData();
|
||||||
list[0] = maxDouble;
|
list[0] = maxDouble;
|
||||||
Expect.equals(list.length, 1);
|
Expect.equals(list.length, 1);
|
||||||
Expect.equals(ptr.load<double>(), maxDouble);
|
Expect.equals(ptr.value, maxDouble);
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ void testArrayLoad() {
|
||||||
const int count = 0x100;
|
const int count = 0x100;
|
||||||
Pointer<Int32> ptr = Pointer.allocate(count: count);
|
Pointer<Int32> ptr = Pointer.allocate(count: count);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
ptr.elementAt(i).store(i);
|
ptr[i] = i;
|
||||||
}
|
}
|
||||||
Int32List array = ptr.asExternalTypedData(count: count);
|
Int32List array = ptr.asExternalTypedData(count: count);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
|
@ -275,7 +275,7 @@ void testArrayStore() {
|
||||||
array[i] = i;
|
array[i] = i;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
Expect.equals(ptr.elementAt(i).load<int>(), i);
|
Expect.equals(ptr[i], i);
|
||||||
}
|
}
|
||||||
ptr.free();
|
ptr.free();
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ double manyArgs(
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef StoreType = Pointer<Int64> Function(Pointer<Int64>);
|
typedef StoreType = Pointer<Int64> Function(Pointer<Int64>);
|
||||||
Pointer<Int64> store(Pointer<Int64> ptr) => ptr.elementAt(1)..store(1337);
|
Pointer<Int64> store(Pointer<Int64> ptr) => ptr.elementAt(1)..value = 1337;
|
||||||
|
|
||||||
typedef NullPointersType = Pointer<Int64> Function(Pointer<Int64>);
|
typedef NullPointersType = Pointer<Int64> Function(Pointer<Int64>);
|
||||||
Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr.elementAt(1);
|
Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr.elementAt(1);
|
||||||
|
@ -182,15 +182,19 @@ void testGC() {
|
||||||
typedef WaitForHelper = Void Function(Pointer<Void>);
|
typedef WaitForHelper = Void Function(Pointer<Void>);
|
||||||
void waitForHelper(Pointer<Void> helper) {
|
void waitForHelper(Pointer<Void> helper) {
|
||||||
print("helper: $helper");
|
print("helper: $helper");
|
||||||
testLibrary.lookupFunction<WaitForHelper, WaitForHelper>("WaitForHelper")(helper);
|
testLibrary
|
||||||
|
.lookupFunction<WaitForHelper, WaitForHelper>("WaitForHelper")(helper);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Test> testcases = [
|
final List<Test> testcases = [
|
||||||
Test("SimpleAddition", Pointer.fromFunction<SimpleAdditionType>(simpleAddition, 0)),
|
Test("SimpleAddition",
|
||||||
Test("IntComputation", Pointer.fromFunction<IntComputationType>(intComputation, 0)),
|
Pointer.fromFunction<SimpleAdditionType>(simpleAddition, 0)),
|
||||||
Test(
|
Test("IntComputation",
|
||||||
"UintComputation", Pointer.fromFunction<UintComputationType>(uintComputation, 0)),
|
Pointer.fromFunction<IntComputationType>(intComputation, 0)),
|
||||||
Test("SimpleMultiply", Pointer.fromFunction<SimpleMultiplyType>(simpleMultiply, 0.0)),
|
Test("UintComputation",
|
||||||
|
Pointer.fromFunction<UintComputationType>(uintComputation, 0)),
|
||||||
|
Test("SimpleMultiply",
|
||||||
|
Pointer.fromFunction<SimpleMultiplyType>(simpleMultiply, 0.0)),
|
||||||
Test("SimpleMultiplyFloat",
|
Test("SimpleMultiplyFloat",
|
||||||
Pointer.fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat, 0.0)),
|
Pointer.fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat, 0.0)),
|
||||||
Test("ManyInts", Pointer.fromFunction<ManyIntsType>(manyInts, 0)),
|
Test("ManyInts", Pointer.fromFunction<ManyIntsType>(manyInts, 0)),
|
||||||
|
@ -202,17 +206,17 @@ final List<Test> testcases = [
|
||||||
Test("ReturnVoid", Pointer.fromFunction<ReturnVoid>(returnVoid)),
|
Test("ReturnVoid", Pointer.fromFunction<ReturnVoid>(returnVoid)),
|
||||||
Test("ThrowExceptionDouble",
|
Test("ThrowExceptionDouble",
|
||||||
Pointer.fromFunction<ThrowExceptionDouble>(throwExceptionDouble, 42.0)),
|
Pointer.fromFunction<ThrowExceptionDouble>(throwExceptionDouble, 42.0)),
|
||||||
Test(
|
Test("ThrowExceptionPointer",
|
||||||
"ThrowExceptionPointer",
|
Pointer.fromFunction<ThrowExceptionPointer>(throwExceptionPointer)),
|
||||||
Pointer.fromFunction<ThrowExceptionPointer>(
|
Test("ThrowException",
|
||||||
throwExceptionPointer)),
|
Pointer.fromFunction<ThrowExceptionInt>(throwExceptionInt, 42)),
|
||||||
Test("ThrowException", Pointer.fromFunction<ThrowExceptionInt>(throwExceptionInt, 42)),
|
|
||||||
Test("GC", Pointer.fromFunction<ReturnVoid>(testGC)),
|
Test("GC", Pointer.fromFunction<ReturnVoid>(testGC)),
|
||||||
Test("UnprotectCode", Pointer.fromFunction<WaitForHelper>(waitForHelper)),
|
Test("UnprotectCode", Pointer.fromFunction<WaitForHelper>(waitForHelper)),
|
||||||
];
|
];
|
||||||
|
|
||||||
testCallbackWrongThread() =>
|
testCallbackWrongThread() =>
|
||||||
Test("CallbackWrongThread", Pointer.fromFunction<ReturnVoid>(returnVoid)).run();
|
Test("CallbackWrongThread", Pointer.fromFunction<ReturnVoid>(returnVoid))
|
||||||
|
.run();
|
||||||
|
|
||||||
testCallbackOutsideIsolate() =>
|
testCallbackOutsideIsolate() =>
|
||||||
Test("CallbackOutsideIsolate", Pointer.fromFunction<ReturnVoid>(returnVoid))
|
Test("CallbackOutsideIsolate", Pointer.fromFunction<ReturnVoid>(returnVoid))
|
||||||
|
@ -227,7 +231,8 @@ isolateHelper(int callbackPointer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
testCallbackWrongIsolate() async {
|
testCallbackWrongIsolate() async {
|
||||||
final int callbackPointer = Pointer.fromFunction<ReturnVoid>(returnVoid).address;
|
final int callbackPointer =
|
||||||
|
Pointer.fromFunction<ReturnVoid>(returnVoid).address;
|
||||||
final ReceivePort exitPort = ReceivePort();
|
final ReceivePort exitPort = ReceivePort();
|
||||||
await Isolate.spawn(isolateHelper, callbackPointer,
|
await Isolate.spawn(isolateHelper, callbackPointer,
|
||||||
errorsAreFatal: true, onExit: exitPort.sendPort);
|
errorsAreFatal: true, onExit: exitPort.sendPort);
|
||||||
|
@ -262,7 +267,7 @@ void main() async {
|
||||||
await testCallbackWrongIsolate(); //# 03: ok
|
await testCallbackWrongIsolate(); //# 03: ok
|
||||||
}
|
}
|
||||||
|
|
||||||
testManyCallbacks(); //# 04: ok
|
testManyCallbacks(); //# 04: ok
|
||||||
}
|
}
|
||||||
|
|
||||||
void testManyCallbacks() {
|
void testManyCallbacks() {
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
|
|
||||||
library FfiTest;
|
library FfiTest;
|
||||||
|
|
||||||
import 'dart:ffi' as ffi;
|
import 'dart:ffi';
|
||||||
import 'dart:ffi' show Pointer;
|
|
||||||
|
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
|
@ -27,24 +26,23 @@ void main() {
|
||||||
testFunctionWithVeryLargeStruct();
|
testFunctionWithVeryLargeStruct();
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi.DynamicLibrary ffiTestFunctions =
|
DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
dlopenPlatformSpecific("ffi_test_functions");
|
|
||||||
|
|
||||||
/// pass a struct to a c function and get a struct as return value
|
/// pass a struct to a c function and get a struct as return value
|
||||||
void testFunctionWithStruct() {
|
void testFunctionWithStruct() {
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
|
Pointer<NativeFunction<NativeCoordinateOp>> p1 =
|
||||||
ffiTestFunctions.lookup("TransposeCoordinate");
|
ffiTestFunctions.lookup("TransposeCoordinate");
|
||||||
NativeCoordinateOp f1 = p1.asFunction();
|
NativeCoordinateOp f1 = p1.asFunction();
|
||||||
|
|
||||||
Pointer<Coordinate> c1 =
|
Pointer<Coordinate> c1 =
|
||||||
Coordinate.allocate(10.0, 20.0, ffi.nullptr.cast<Coordinate>()).addressOf;
|
Coordinate.allocate(10.0, 20.0, nullptr.cast<Coordinate>()).addressOf;
|
||||||
Pointer<Coordinate> c2 = Coordinate.allocate(42.0, 84.0, c1).addressOf;
|
Pointer<Coordinate> c2 = Coordinate.allocate(42.0, 84.0, c1).addressOf;
|
||||||
c1.load<Coordinate>().next = c2;
|
c1.ref.next = c2;
|
||||||
|
|
||||||
Coordinate result = f1(c1).load();
|
Coordinate result = f1(c1).ref;
|
||||||
|
|
||||||
Expect.approxEquals(20.0, c1.load<Coordinate>().x);
|
Expect.approxEquals(20.0, c1.ref.x);
|
||||||
Expect.approxEquals(30.0, c1.load<Coordinate>().y);
|
Expect.approxEquals(30.0, c1.ref.y);
|
||||||
|
|
||||||
Expect.approxEquals(42.0, result.x);
|
Expect.approxEquals(42.0, result.x);
|
||||||
Expect.approxEquals(84.0, result.y);
|
Expect.approxEquals(84.0, result.y);
|
||||||
|
@ -55,13 +53,13 @@ void testFunctionWithStruct() {
|
||||||
|
|
||||||
/// pass an array of structs to a c funtion
|
/// pass an array of structs to a c funtion
|
||||||
void testFunctionWithStructArray() {
|
void testFunctionWithStructArray() {
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
|
Pointer<NativeFunction<NativeCoordinateOp>> p1 =
|
||||||
ffiTestFunctions.lookup("CoordinateElemAt1");
|
ffiTestFunctions.lookup("CoordinateElemAt1");
|
||||||
NativeCoordinateOp f1 = p1.asFunction();
|
NativeCoordinateOp f1 = p1.asFunction();
|
||||||
|
|
||||||
Coordinate c1 = Pointer<Coordinate>.allocate(count: 3).load();
|
Coordinate c1 = Pointer<Coordinate>.allocate(count: 3).ref;
|
||||||
Coordinate c2 = c1.addressOf.elementAt(1).load();
|
Coordinate c2 = c1.addressOf[1];
|
||||||
Coordinate c3 = c1.addressOf.elementAt(2).load();
|
Coordinate c3 = c1.addressOf[2];
|
||||||
c1.x = 10.0;
|
c1.x = 10.0;
|
||||||
c1.y = 10.0;
|
c1.y = 10.0;
|
||||||
c1.next = c3.addressOf;
|
c1.next = c3.addressOf;
|
||||||
|
@ -72,7 +70,7 @@ void testFunctionWithStructArray() {
|
||||||
c3.y = 30.0;
|
c3.y = 30.0;
|
||||||
c3.next = c2.addressOf;
|
c3.next = c2.addressOf;
|
||||||
|
|
||||||
Coordinate result = f1(c1.addressOf).load();
|
Coordinate result = f1(c1.addressOf).ref;
|
||||||
Expect.approxEquals(20.0, result.x);
|
Expect.approxEquals(20.0, result.x);
|
||||||
Expect.approxEquals(20.0, result.y);
|
Expect.approxEquals(20.0, result.y);
|
||||||
|
|
||||||
|
@ -80,15 +78,15 @@ void testFunctionWithStructArray() {
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef VeryLargeStructSum = int Function(Pointer<VeryLargeStruct>);
|
typedef VeryLargeStructSum = int Function(Pointer<VeryLargeStruct>);
|
||||||
typedef NativeVeryLargeStructSum = ffi.Int64 Function(Pointer<VeryLargeStruct>);
|
typedef NativeVeryLargeStructSum = Int64 Function(Pointer<VeryLargeStruct>);
|
||||||
|
|
||||||
void testFunctionWithVeryLargeStruct() {
|
void testFunctionWithVeryLargeStruct() {
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeVeryLargeStructSum>> p1 =
|
Pointer<NativeFunction<NativeVeryLargeStructSum>> p1 =
|
||||||
ffiTestFunctions.lookup("SumVeryLargeStruct");
|
ffiTestFunctions.lookup("SumVeryLargeStruct");
|
||||||
VeryLargeStructSum f = p1.asFunction();
|
VeryLargeStructSum f = p1.asFunction();
|
||||||
|
|
||||||
VeryLargeStruct vls1 = Pointer<VeryLargeStruct>.allocate(count: 2).load();
|
VeryLargeStruct vls1 = Pointer<VeryLargeStruct>.allocate(count: 2).ref;
|
||||||
VeryLargeStruct vls2 = vls1.addressOf.elementAt(1).load();
|
VeryLargeStruct vls2 = vls1.addressOf[1];
|
||||||
List<VeryLargeStruct> structs = [vls1, vls2];
|
List<VeryLargeStruct> structs = [vls1, vls2];
|
||||||
for (VeryLargeStruct struct in structs) {
|
for (VeryLargeStruct struct in structs) {
|
||||||
struct.a = 1;
|
struct.a = 1;
|
||||||
|
@ -108,9 +106,9 @@ void testFunctionWithVeryLargeStruct() {
|
||||||
vls1.numChildren = 2;
|
vls1.numChildren = 2;
|
||||||
vls1.children = vls1.addressOf;
|
vls1.children = vls1.addressOf;
|
||||||
vls2.parent = vls2.addressOf;
|
vls2.parent = vls2.addressOf;
|
||||||
vls2.parent = ffi.nullptr.cast();
|
vls2.parent = nullptr.cast();
|
||||||
vls2.numChildren = 0;
|
vls2.numChildren = 0;
|
||||||
vls2.children = ffi.nullptr.cast();
|
vls2.children = nullptr.cast();
|
||||||
|
|
||||||
int result = f(vls1.addressOf);
|
int result = f(vls1.addressOf);
|
||||||
Expect.equals(2051, result);
|
Expect.equals(2051, result);
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
|
|
||||||
library FfiTest;
|
library FfiTest;
|
||||||
|
|
||||||
import 'dart:ffi' as ffi;
|
import 'dart:ffi';
|
||||||
import 'dart:ffi' show Pointer;
|
|
||||||
|
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
|
@ -47,27 +46,24 @@ void main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi.DynamicLibrary ffiTestFunctions =
|
DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
||||||
dlopenPlatformSpecific("ffi_test_functions");
|
|
||||||
|
|
||||||
typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32);
|
typedef NativeBinaryOp = Int32 Function(Int32, Int32);
|
||||||
typedef UnaryOp = int Function(int);
|
typedef UnaryOp = int Function(int);
|
||||||
typedef BinaryOp = int Function(int, int);
|
typedef BinaryOp = int Function(int, int);
|
||||||
typedef GenericBinaryOp<T> = int Function(int, T);
|
typedef GenericBinaryOp<T> = int Function(int, T);
|
||||||
|
|
||||||
void testNativeFunctionFromCast() {
|
void testNativeFunctionFromCast() {
|
||||||
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
|
Pointer<IntPtr> p1 = Pointer.allocate();
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeBinaryOp>> p2 = p1.cast();
|
Pointer<NativeFunction<NativeBinaryOp>> p2 = p1.cast();
|
||||||
p2.asFunction<BinaryOp>();
|
p2.asFunction<BinaryOp>();
|
||||||
p2.asFunction<GenericBinaryOp<int>>();
|
p2.asFunction<GenericBinaryOp<int>>();
|
||||||
p1.free();
|
p1.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeQuadOpSigned = ffi.Int64 Function(
|
typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
|
||||||
ffi.Int8, ffi.Int16, ffi.Int32, ffi.Int64);
|
|
||||||
typedef QuadOp = int Function(int, int, int, int);
|
typedef QuadOp = int Function(int, int, int, int);
|
||||||
typedef NativeQuadOpUnsigned = ffi.Uint64 Function(
|
typedef NativeQuadOpUnsigned = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
|
||||||
ffi.Uint8, ffi.Uint16, ffi.Uint32, ffi.Uint64);
|
|
||||||
|
|
||||||
BinaryOp sumPlus42 =
|
BinaryOp sumPlus42 =
|
||||||
ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
|
ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
|
||||||
|
@ -86,76 +82,76 @@ void testNativeFunctionFromLookup() {
|
||||||
-0x8000000000000000, intComputation(0, 0, 0, -0x8000000000000000));
|
-0x8000000000000000, intComputation(0, 0, 0, -0x8000000000000000));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeReturnMaxUint8 = ffi.Uint8 Function();
|
typedef NativeReturnMaxUint8 = Uint8 Function();
|
||||||
int Function() returnMaxUint8 = ffiTestFunctions
|
int Function() returnMaxUint8 = ffiTestFunctions
|
||||||
.lookup("ReturnMaxUint8")
|
.lookup("ReturnMaxUint8")
|
||||||
.cast<ffi.NativeFunction<NativeReturnMaxUint8>>()
|
.cast<NativeFunction<NativeReturnMaxUint8>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeReturnMaxUint16 = ffi.Uint16 Function();
|
typedef NativeReturnMaxUint16 = Uint16 Function();
|
||||||
int Function() returnMaxUint16 = ffiTestFunctions
|
int Function() returnMaxUint16 = ffiTestFunctions
|
||||||
.lookup("ReturnMaxUint16")
|
.lookup("ReturnMaxUint16")
|
||||||
.cast<ffi.NativeFunction<NativeReturnMaxUint16>>()
|
.cast<NativeFunction<NativeReturnMaxUint16>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeReturnMaxUint32 = ffi.Uint32 Function();
|
typedef NativeReturnMaxUint32 = Uint32 Function();
|
||||||
int Function() returnMaxUint32 = ffiTestFunctions
|
int Function() returnMaxUint32 = ffiTestFunctions
|
||||||
.lookup("ReturnMaxUint32")
|
.lookup("ReturnMaxUint32")
|
||||||
.cast<ffi.NativeFunction<NativeReturnMaxUint32>>()
|
.cast<NativeFunction<NativeReturnMaxUint32>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeReturnMinInt8 = ffi.Int8 Function();
|
typedef NativeReturnMinInt8 = Int8 Function();
|
||||||
int Function() returnMinInt8 = ffiTestFunctions
|
int Function() returnMinInt8 = ffiTestFunctions
|
||||||
.lookup("ReturnMinInt8")
|
.lookup("ReturnMinInt8")
|
||||||
.cast<ffi.NativeFunction<NativeReturnMinInt8>>()
|
.cast<NativeFunction<NativeReturnMinInt8>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeReturnMinInt16 = ffi.Int16 Function();
|
typedef NativeReturnMinInt16 = Int16 Function();
|
||||||
int Function() returnMinInt16 = ffiTestFunctions
|
int Function() returnMinInt16 = ffiTestFunctions
|
||||||
.lookup("ReturnMinInt16")
|
.lookup("ReturnMinInt16")
|
||||||
.cast<ffi.NativeFunction<NativeReturnMinInt16>>()
|
.cast<NativeFunction<NativeReturnMinInt16>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeReturnMinInt32 = ffi.Int32 Function();
|
typedef NativeReturnMinInt32 = Int32 Function();
|
||||||
int Function() returnMinInt32 = ffiTestFunctions
|
int Function() returnMinInt32 = ffiTestFunctions
|
||||||
.lookup("ReturnMinInt32")
|
.lookup("ReturnMinInt32")
|
||||||
.cast<ffi.NativeFunction<NativeReturnMinInt32>>()
|
.cast<NativeFunction<NativeReturnMinInt32>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeTakeMaxUint8 = ffi.IntPtr Function(ffi.Uint8);
|
typedef NativeTakeMaxUint8 = IntPtr Function(Uint8);
|
||||||
int Function(int) takeMaxUint8 = ffiTestFunctions
|
int Function(int) takeMaxUint8 = ffiTestFunctions
|
||||||
.lookup("TakeMaxUint8")
|
.lookup("TakeMaxUint8")
|
||||||
.cast<ffi.NativeFunction<NativeTakeMaxUint8>>()
|
.cast<NativeFunction<NativeTakeMaxUint8>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeTakeMaxUint16 = ffi.IntPtr Function(ffi.Uint16);
|
typedef NativeTakeMaxUint16 = IntPtr Function(Uint16);
|
||||||
int Function(int) takeMaxUint16 = ffiTestFunctions
|
int Function(int) takeMaxUint16 = ffiTestFunctions
|
||||||
.lookup("TakeMaxUint16")
|
.lookup("TakeMaxUint16")
|
||||||
.cast<ffi.NativeFunction<NativeTakeMaxUint16>>()
|
.cast<NativeFunction<NativeTakeMaxUint16>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeTakeMaxUint32 = ffi.IntPtr Function(ffi.Uint32);
|
typedef NativeTakeMaxUint32 = IntPtr Function(Uint32);
|
||||||
int Function(int) takeMaxUint32 = ffiTestFunctions
|
int Function(int) takeMaxUint32 = ffiTestFunctions
|
||||||
.lookup("TakeMaxUint32")
|
.lookup("TakeMaxUint32")
|
||||||
.cast<ffi.NativeFunction<NativeTakeMaxUint32>>()
|
.cast<NativeFunction<NativeTakeMaxUint32>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeTakeMinInt8 = ffi.IntPtr Function(ffi.Int8);
|
typedef NativeTakeMinInt8 = IntPtr Function(Int8);
|
||||||
int Function(int) takeMinInt8 = ffiTestFunctions
|
int Function(int) takeMinInt8 = ffiTestFunctions
|
||||||
.lookup("TakeMinInt8")
|
.lookup("TakeMinInt8")
|
||||||
.cast<ffi.NativeFunction<NativeTakeMinInt8>>()
|
.cast<NativeFunction<NativeTakeMinInt8>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeTakeMinInt16 = ffi.IntPtr Function(ffi.Int16);
|
typedef NativeTakeMinInt16 = IntPtr Function(Int16);
|
||||||
int Function(int) takeMinInt16 = ffiTestFunctions
|
int Function(int) takeMinInt16 = ffiTestFunctions
|
||||||
.lookup("TakeMinInt16")
|
.lookup("TakeMinInt16")
|
||||||
.cast<ffi.NativeFunction<NativeTakeMinInt16>>()
|
.cast<NativeFunction<NativeTakeMinInt16>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
typedef NativeTakeMinInt32 = ffi.IntPtr Function(ffi.Int32);
|
typedef NativeTakeMinInt32 = IntPtr Function(Int32);
|
||||||
int Function(int) takeMinInt32 = ffiTestFunctions
|
int Function(int) takeMinInt32 = ffiTestFunctions
|
||||||
.lookup("TakeMinInt32")
|
.lookup("TakeMinInt32")
|
||||||
.cast<ffi.NativeFunction<NativeTakeMinInt32>>()
|
.cast<NativeFunction<NativeTakeMinInt32>>()
|
||||||
.asFunction();
|
.asFunction();
|
||||||
|
|
||||||
void testExtension() {
|
void testExtension() {
|
||||||
|
@ -188,8 +184,8 @@ void test64bitInterpretations() {
|
||||||
Expect.equals(-1, uintComputation(0, 0, 0, -1));
|
Expect.equals(-1, uintComputation(0, 0, 0, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeSenaryOp = ffi.Int64 Function(
|
typedef NativeSenaryOp = Int64 Function(
|
||||||
ffi.Int8, ffi.Int16, ffi.Int32, ffi.Uint8, ffi.Uint16, ffi.Uint32);
|
Int8, Int16, Int32, Uint8, Uint16, Uint32);
|
||||||
typedef SenaryOp = int Function(int, int, int, int, int, int);
|
typedef SenaryOp = int Function(int, int, int, int, int, int);
|
||||||
|
|
||||||
SenaryOp sumSmallNumbers = ffiTestFunctions
|
SenaryOp sumSmallNumbers = ffiTestFunctions
|
||||||
|
@ -213,7 +209,7 @@ void testTruncation() {
|
||||||
Expect.equals(0xFFFFFFFF, sumSmallNumbers(0, 0, 0, 0, 0, -1));
|
Expect.equals(0xFFFFFFFF, sumSmallNumbers(0, 0, 0, 0, 0, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeDoubleUnaryOp = ffi.Double Function(ffi.Double);
|
typedef NativeDoubleUnaryOp = Double Function(Double);
|
||||||
typedef DoubleUnaryOp = double Function(double);
|
typedef DoubleUnaryOp = double Function(double);
|
||||||
|
|
||||||
DoubleUnaryOp times1_337Double = ffiTestFunctions
|
DoubleUnaryOp times1_337Double = ffiTestFunctions
|
||||||
|
@ -223,7 +219,7 @@ void testNativeFunctionDoubles() {
|
||||||
Expect.approxEquals(2.0 * 1.337, times1_337Double(2.0));
|
Expect.approxEquals(2.0 * 1.337, times1_337Double(2.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeFloatUnaryOp = ffi.Float Function(ffi.Float);
|
typedef NativeFloatUnaryOp = Float Function(Float);
|
||||||
|
|
||||||
DoubleUnaryOp times1_337Float = ffiTestFunctions
|
DoubleUnaryOp times1_337Float = ffiTestFunctions
|
||||||
.lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
|
.lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
|
||||||
|
@ -232,17 +228,8 @@ void testNativeFunctionFloats() {
|
||||||
Expect.approxEquals(1337.0, times1_337Float(1000.0));
|
Expect.approxEquals(1337.0, times1_337Float(1000.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeDecenaryOp = ffi.IntPtr Function(
|
typedef NativeDecenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
|
||||||
ffi.IntPtr,
|
IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr);
|
|
||||||
typedef DecenaryOp = int Function(
|
typedef DecenaryOp = int Function(
|
||||||
int, int, int, int, int, int, int, int, int, int);
|
int, int, int, int, int, int, int, int, int, int);
|
||||||
|
|
||||||
|
@ -253,18 +240,8 @@ void testNativeFunctionManyArguments1() {
|
||||||
Expect.equals(55, sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
|
Expect.equals(55, sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeUndenaryOp = ffi.IntPtr Function(
|
typedef NativeUndenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
|
||||||
ffi.IntPtr,
|
IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr,
|
|
||||||
ffi.IntPtr);
|
|
||||||
typedef UndenaryOp = int Function(
|
typedef UndenaryOp = int Function(
|
||||||
int, int, int, int, int, int, int, int, int, int, int);
|
int, int, int, int, int, int, int, int, int, int, int);
|
||||||
|
|
||||||
|
@ -275,17 +252,8 @@ void testNativeFunctionManyArguments4() {
|
||||||
Expect.equals(66, sumManyIntsOdd(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
|
Expect.equals(66, sumManyIntsOdd(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeDoubleDecenaryOp = ffi.Double Function(
|
typedef NativeDoubleDecenaryOp = Double Function(Double, Double, Double, Double,
|
||||||
ffi.Double,
|
Double, Double, Double, Double, Double, Double);
|
||||||
ffi.Double,
|
|
||||||
ffi.Double,
|
|
||||||
ffi.Double,
|
|
||||||
ffi.Double,
|
|
||||||
ffi.Double,
|
|
||||||
ffi.Double,
|
|
||||||
ffi.Double,
|
|
||||||
ffi.Double,
|
|
||||||
ffi.Double);
|
|
||||||
typedef DoubleDecenaryOp = double Function(double, double, double, double,
|
typedef DoubleDecenaryOp = double Function(double, double, double, double,
|
||||||
double, double, double, double, double, double);
|
double, double, double, double, double, double);
|
||||||
|
|
||||||
|
@ -297,27 +265,27 @@ void testNativeFunctionManyArguments2() {
|
||||||
55.0, sumManyDoubles(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0));
|
55.0, sumManyDoubles(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeVigesimalOp = ffi.Double Function(
|
typedef NativeVigesimalOp = Double Function(
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Float,
|
Float,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Double,
|
Double,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Float,
|
Float,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Double,
|
Double,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Float,
|
Float,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Double,
|
Double,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Float,
|
Float,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Double,
|
Double,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Float,
|
Float,
|
||||||
ffi.IntPtr,
|
IntPtr,
|
||||||
ffi.Double);
|
Double);
|
||||||
typedef VigesimalOp = double Function(
|
typedef VigesimalOp = double Function(
|
||||||
int,
|
int,
|
||||||
double,
|
double,
|
||||||
|
@ -350,19 +318,18 @@ void testNativeFunctionManyArguments3() {
|
||||||
14.0, 15, 16.0, 17, 18.0, 19, 20.0));
|
14.0, 15, 16.0, 17, 18.0, 19, 20.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Int64PointerUnOp = ffi.Pointer<ffi.Int64> Function(
|
typedef Int64PointerUnOp = Pointer<Int64> Function(Pointer<Int64>);
|
||||||
ffi.Pointer<ffi.Int64>);
|
|
||||||
|
|
||||||
Int64PointerUnOp assign1337Index1 = ffiTestFunctions
|
Int64PointerUnOp assign1337Index1 = ffiTestFunctions
|
||||||
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
|
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
|
||||||
|
|
||||||
void testNativeFunctionPointer() {
|
void testNativeFunctionPointer() {
|
||||||
ffi.Pointer<ffi.Int64> p2 = Pointer.allocate(count: 2);
|
Pointer<Int64> p2 = Pointer.allocate(count: 2);
|
||||||
p2.store(42);
|
p2.value = 42;
|
||||||
p2.elementAt(1).store(1000);
|
p2[1] = 1000;
|
||||||
ffi.Pointer<ffi.Int64> result = assign1337Index1(p2);
|
Pointer<Int64> result = assign1337Index1(p2);
|
||||||
Expect.equals(1337, result.load<int>());
|
Expect.equals(1337, result.value);
|
||||||
Expect.equals(1337, p2.elementAt(1).load<int>());
|
Expect.equals(1337, p2[1]);
|
||||||
Expect.equals(p2.elementAt(1).address, result.address);
|
Expect.equals(p2.elementAt(1).address, result.address);
|
||||||
p2.free();
|
p2.free();
|
||||||
}
|
}
|
||||||
|
@ -387,24 +354,24 @@ Int64PointerUnOp nullableInt64ElemAt1 = ffiTestFunctions
|
||||||
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("NullableInt64ElemAt1");
|
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("NullableInt64ElemAt1");
|
||||||
|
|
||||||
void testNullPointers() {
|
void testNullPointers() {
|
||||||
Pointer<ffi.Int64> result = nullableInt64ElemAt1(ffi.nullptr.cast());
|
Pointer<Int64> result = nullableInt64ElemAt1(nullptr.cast());
|
||||||
Expect.equals(result, ffi.nullptr);
|
Expect.equals(result, nullptr);
|
||||||
|
|
||||||
Pointer<ffi.Int64> p2 = Pointer.allocate(count: 2);
|
Pointer<Int64> p2 = Pointer.allocate(count: 2);
|
||||||
result = nullableInt64ElemAt1(p2);
|
result = nullableInt64ElemAt1(p2);
|
||||||
Expect.notEquals(result, ffi.nullptr);
|
Expect.notEquals(result, nullptr);
|
||||||
p2.free();
|
p2.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeFloatPointerToBool = ffi.Uint8 Function(ffi.Pointer<ffi.Float>);
|
typedef NativeFloatPointerToBool = Uint8 Function(Pointer<Float>);
|
||||||
typedef FloatPointerToBool = int Function(ffi.Pointer<ffi.Float>);
|
typedef FloatPointerToBool = int Function(Pointer<Float>);
|
||||||
|
|
||||||
FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
|
FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
|
||||||
NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
|
NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
|
||||||
|
|
||||||
void testFloatRounding() {
|
void testFloatRounding() {
|
||||||
Pointer<ffi.Float> p2 = Pointer.allocate();
|
Pointer<Float> p2 = Pointer.allocate();
|
||||||
p2.store(1337.0);
|
p2.value = 1337.0;
|
||||||
|
|
||||||
int result = isRoughly1337(p2);
|
int result = isRoughly1337(p2);
|
||||||
Expect.equals(1, result);
|
Expect.equals(1, result);
|
||||||
|
@ -412,7 +379,7 @@ void testFloatRounding() {
|
||||||
p2.free();
|
p2.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeFloatToVoid = ffi.Void Function(ffi.Float);
|
typedef NativeFloatToVoid = Void Function(Float);
|
||||||
typedef DoubleToVoid = void Function(double);
|
typedef DoubleToVoid = void Function(double);
|
||||||
|
|
||||||
DoubleToVoid devNullFloat = ffiTestFunctions
|
DoubleToVoid devNullFloat = ffiTestFunctions
|
||||||
|
@ -426,7 +393,7 @@ void testVoidReturn() {
|
||||||
Expect.isNull(result);
|
Expect.isNull(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeVoidToFloat = ffi.Float Function();
|
typedef NativeVoidToFloat = Float Function();
|
||||||
typedef VoidToDouble = double Function();
|
typedef VoidToDouble = double Function();
|
||||||
|
|
||||||
VoidToDouble inventFloatValue = ffiTestFunctions
|
VoidToDouble inventFloatValue = ffiTestFunctions
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
// Note #2: When we switch to extension methods we will _only_ use the static
|
// Note #2: When we switch to extension methods we will _only_ use the static
|
||||||
// type of the container.
|
// type of the container.
|
||||||
//
|
//
|
||||||
// ===== a.store(b) ======
|
// ===== a.value = b ======
|
||||||
// Does a.store(b), where a and b have specific static and dynamic types: run
|
// Does a.value = b, where a and b have specific static and dynamic types: run
|
||||||
// fine, fail at compile time, or fail at runtime?
|
// fine, fail at compile time, or fail at runtime?
|
||||||
// =======================
|
// =======================
|
||||||
// b P<I>//P<I> P<NT>//P<I> P<NT>//P<NT>
|
// b P<I>//P<I> P<NT>//P<I> P<NT>//P<NT>
|
||||||
|
@ -29,11 +29,11 @@
|
||||||
//
|
//
|
||||||
// P<P<NT>>//P<P<NT>> 7 ok 8 ok 9 ok
|
// P<P<NT>>//P<P<NT>> 7 ok 8 ok 9 ok
|
||||||
//
|
//
|
||||||
// ====== final c = a.load() ======
|
// ====== final c = a.value ======
|
||||||
// What is the (inferred) static type and runtime type of `a.load()`. Note that
|
// What is the (inferred) static type and runtime type of `a.value`. Note that
|
||||||
// we assume extension method here: on Pointer<PointerT>> { Pointer<T> load(); }
|
// we assume extension method here: on Pointer<PointerT>> { Pointer<T> load(); }
|
||||||
// ================================
|
// ================================
|
||||||
// a a.load()
|
// a a.value
|
||||||
// inferred static type*//runtime type
|
// inferred static type*//runtime type
|
||||||
// P<P<I>>//P<P<I>> P<I>//P<I>
|
// P<P<I>>//P<P<I>> P<I>//P<I>
|
||||||
//
|
//
|
||||||
|
@ -43,8 +43,8 @@
|
||||||
//
|
//
|
||||||
// * The inferred static type when we get extension methods.
|
// * The inferred static type when we get extension methods.
|
||||||
//
|
//
|
||||||
// ====== b = a.load() ======
|
// ====== b = a.value ======
|
||||||
// What happens when we try to assign the result of a.load() to variable b with
|
// What happens when we try to assign the result of a.value to variable b with
|
||||||
// a specific static type: runs fine, fails at compile time, or fails at runtime.
|
// a specific static type: runs fine, fails at compile time, or fails at runtime.
|
||||||
// ==========================
|
// ==========================
|
||||||
// b P<I> P<NT>
|
// b P<I> P<NT>
|
||||||
|
@ -64,13 +64,13 @@ import 'dart:ffi';
|
||||||
|
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
// ===== a.store(b) ======
|
// ===== a.value = b ======
|
||||||
// The tests follow table cells left to right, top to bottom.
|
// The tests follow table cells left to right, top to bottom.
|
||||||
void store1() {
|
void store1() {
|
||||||
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
|
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
|
||||||
final Pointer<Int8> b = Pointer<Int8>.allocate();
|
final Pointer<Int8> b = Pointer<Int8>.allocate();
|
||||||
|
|
||||||
a.store(b);
|
a.value = b;
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
|
@ -81,8 +81,9 @@ void store2() {
|
||||||
final Pointer<NativeType> b =
|
final Pointer<NativeType> b =
|
||||||
Pointer<Int8>.allocate(); // Reified Pointer<Int8> at runtime.
|
Pointer<Int8>.allocate(); // Reified Pointer<Int8> at runtime.
|
||||||
|
|
||||||
// We disable implicit downcasts, they will go away when NNBD lands.
|
// Successful implicit downcast of argument at runtime.
|
||||||
a.store(b); //# 1: compile-time error
|
// Should succeed now, should statically be rejected when NNBD lands.
|
||||||
|
a.value = b;
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
|
@ -93,8 +94,11 @@ void store3() {
|
||||||
final Pointer<NativeType> b =
|
final Pointer<NativeType> b =
|
||||||
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
|
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
|
||||||
|
|
||||||
// We disable implicit downcasts, they will go away when NNBD lands.
|
// Failing implicit downcast of argument at runtime.
|
||||||
a.store(b); //# 2: compile-time error
|
// Should fail now at runtime, should statically be rejected when NNBD lands.
|
||||||
|
Expect.throws(() {
|
||||||
|
a.value = b;
|
||||||
|
});
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
|
@ -106,7 +110,7 @@ void store4() {
|
||||||
|
|
||||||
final Pointer<Int8> b = Pointer<Int8>.allocate();
|
final Pointer<Int8> b = Pointer<Int8>.allocate();
|
||||||
|
|
||||||
a.store(b);
|
a.value = b;
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
|
@ -119,7 +123,7 @@ void store5() {
|
||||||
final Pointer<NativeType> b =
|
final Pointer<NativeType> b =
|
||||||
Pointer<Int8>.allocate(); // Reified as Pointer<Int8> at runtime.
|
Pointer<Int8>.allocate(); // Reified as Pointer<Int8> at runtime.
|
||||||
|
|
||||||
a.store(b);
|
a.value = b;
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
|
@ -133,7 +137,7 @@ void store6() {
|
||||||
|
|
||||||
// Fails on type check of argument.
|
// Fails on type check of argument.
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
a.store(b);
|
a.value = b;
|
||||||
});
|
});
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
|
@ -145,7 +149,7 @@ void store7() {
|
||||||
Pointer<Pointer<NativeType>>.allocate();
|
Pointer<Pointer<NativeType>>.allocate();
|
||||||
final Pointer<Int8> b = Pointer<Int8>.allocate();
|
final Pointer<Int8> b = Pointer<Int8>.allocate();
|
||||||
|
|
||||||
a.store(b);
|
a.value = b;
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
|
@ -158,7 +162,7 @@ void store8() {
|
||||||
// Reified as Pointer<Int8> at runtime.
|
// Reified as Pointer<Int8> at runtime.
|
||||||
final Pointer<NativeType> b = Pointer<Int8>.allocate();
|
final Pointer<NativeType> b = Pointer<Int8>.allocate();
|
||||||
|
|
||||||
a.store(b);
|
a.value = b;
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
|
@ -170,18 +174,18 @@ void store9() {
|
||||||
final Pointer<NativeType> b =
|
final Pointer<NativeType> b =
|
||||||
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
|
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
|
||||||
|
|
||||||
a.store(b);
|
a.value = b;
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
b.free();
|
b.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====== b = a.load() ======
|
// ====== b = a.value ======
|
||||||
// The tests follow table cells left to right, top to bottom.
|
// The tests follow table cells left to right, top to bottom.
|
||||||
void load1() {
|
void load1() {
|
||||||
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
|
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
|
||||||
|
|
||||||
Pointer<Int8> b = a.load();
|
Pointer<Int8> b = a.value;
|
||||||
Expect.type<Pointer<Int8>>(b);
|
Expect.type<Pointer<Int8>>(b);
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
|
@ -190,7 +194,7 @@ void load1() {
|
||||||
void load2() {
|
void load2() {
|
||||||
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
|
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
|
||||||
|
|
||||||
Pointer<NativeType> b = a.load<Pointer<Int8>>();
|
Pointer<NativeType> b = a.value;
|
||||||
Expect.type<Pointer<Int8>>(b);
|
Expect.type<Pointer<Int8>>(b);
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
|
@ -200,7 +204,7 @@ void load3() {
|
||||||
// Reified as Pointer<Pointer<Int8>> at runtime.
|
// Reified as Pointer<Pointer<Int8>> at runtime.
|
||||||
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
|
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
|
||||||
|
|
||||||
Pointer<Int8> b = a.load<Pointer<NativeType>>();
|
Pointer<Int8> b = a.value;
|
||||||
Expect.type<Pointer<Int8>>(b);
|
Expect.type<Pointer<Int8>>(b);
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
|
@ -211,7 +215,7 @@ void load4() {
|
||||||
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
|
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
|
||||||
|
|
||||||
// Return value runtime type is Pointer<Int8>.
|
// Return value runtime type is Pointer<Int8>.
|
||||||
Pointer<NativeType> b = a.load();
|
Pointer<NativeType> b = a.value;
|
||||||
Expect.type<Pointer<Int8>>(b);
|
Expect.type<Pointer<Int8>>(b);
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
|
@ -224,7 +228,7 @@ void load5() {
|
||||||
// Failing implicit downcast of return value at runtime.
|
// Failing implicit downcast of return value at runtime.
|
||||||
// Should fail now at runtime, should statically be rejected when NNBD lands.
|
// Should fail now at runtime, should statically be rejected when NNBD lands.
|
||||||
Expect.throws(() {
|
Expect.throws(() {
|
||||||
Pointer<Int8> b = a.load<Pointer<NativeType>>();
|
Pointer<Int8> b = a.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
|
@ -234,7 +238,7 @@ void load6() {
|
||||||
final Pointer<Pointer<NativeType>> a =
|
final Pointer<Pointer<NativeType>> a =
|
||||||
Pointer<Pointer<NativeType>>.allocate();
|
Pointer<Pointer<NativeType>>.allocate();
|
||||||
|
|
||||||
Pointer<NativeType> b = a.load();
|
Pointer<NativeType> b = a.value;
|
||||||
Expect.type<Pointer<NativeType>>(b);
|
Expect.type<Pointer<NativeType>>(b);
|
||||||
|
|
||||||
a.free();
|
a.free();
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
|
|
||||||
library FfiTest;
|
library FfiTest;
|
||||||
|
|
||||||
import 'dart:ffi' as ffi;
|
import 'dart:ffi';
|
||||||
import 'dart:ffi' show Pointer;
|
|
||||||
|
|
||||||
import 'dylib_utils.dart';
|
import 'dylib_utils.dart';
|
||||||
|
|
||||||
|
@ -47,29 +46,29 @@ void main() {
|
||||||
testNativeFunctionSignatureInvalidOptionalPositional();
|
testNativeFunctionSignatureInvalidOptionalPositional();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Int8UnOp = ffi.Int8 Function(ffi.Int8);
|
typedef Int8UnOp = Int8 Function(Int8);
|
||||||
typedef IntUnOp = int Function(int);
|
typedef IntUnOp = int Function(int);
|
||||||
|
|
||||||
void testGetGeneric() {
|
void testGetGeneric() {
|
||||||
int generic(ffi.Pointer p) {
|
int generic(Pointer p) {
|
||||||
int result;
|
int result;
|
||||||
result = p.load<int>(); //# 20: compile-time error
|
result = p.value; //# 20: compile-time error
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
Pointer<Int8> p = Pointer.allocate();
|
||||||
p.store(123);
|
p.value = 123;
|
||||||
ffi.Pointer loseType = p;
|
Pointer loseType = p;
|
||||||
generic(loseType);
|
generic(loseType);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testGetGeneric2() {
|
void testGetGeneric2() {
|
||||||
T generic<T extends Object>() {
|
T generic<T extends Object>() {
|
||||||
Pointer<ffi.Int8> p = Pointer.allocate();
|
Pointer<Int8> p = Pointer.allocate();
|
||||||
p.store(123);
|
p.value = 123;
|
||||||
T result;
|
T result;
|
||||||
result = p.load<T>(); //# 21: compile-time error
|
result = p.value; //# 21: compile-time error
|
||||||
p.free();
|
p.free();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -78,50 +77,50 @@ void testGetGeneric2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testGetVoid() {
|
void testGetVoid() {
|
||||||
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
|
Pointer<IntPtr> p1 = Pointer.allocate();
|
||||||
ffi.Pointer<ffi.Void> p2 = p1.cast();
|
Pointer<Void> p2 = p1.cast();
|
||||||
|
|
||||||
p2.load<int>(); //# 22: compile-time error
|
p2.value; //# 22: compile-time error
|
||||||
|
|
||||||
p1.free();
|
p1.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testGetNativeFunction() {
|
void testGetNativeFunction() {
|
||||||
Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
||||||
IntUnOp f = p.load(); //# 23: compile-time error
|
IntUnOp f = p.value; //# 23: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
void testGetNativeType() {
|
void testGetNativeType() {
|
||||||
// Is it possible to obtain a ffi.Pointer<ffi.NativeType> at all?
|
// Is it possible to obtain a Pointer<NativeType> at all?
|
||||||
}
|
}
|
||||||
|
|
||||||
void testGetTypeMismatch() {
|
void testGetTypeMismatch() {
|
||||||
ffi.Pointer<ffi.Pointer<ffi.Int16>> p = Pointer.allocate();
|
Pointer<Pointer<Int16>> p = Pointer.allocate();
|
||||||
ffi.Pointer<ffi.Int16> typedNull = ffi.nullptr.cast();
|
Pointer<Int16> typedNull = nullptr.cast();
|
||||||
p.store(typedNull);
|
p.value = typedNull;
|
||||||
|
|
||||||
// this fails to compile due to type mismatch
|
// this fails to compile due to type mismatch
|
||||||
ffi.Pointer<ffi.Int8> p2 = p.load(); //# 25: compile-time error
|
Pointer<Int8> p2 = p.value; //# 25: compile-time error
|
||||||
|
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSetGeneric() {
|
void testSetGeneric() {
|
||||||
void generic(ffi.Pointer p) {
|
void generic(Pointer p) {
|
||||||
p.store(123); //# 26: compile-time error
|
p.value = 123; //# 26: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
Pointer<Int8> p = Pointer.allocate();
|
||||||
p.store(123);
|
p.value = 123;
|
||||||
ffi.Pointer loseType = p;
|
Pointer loseType = p;
|
||||||
generic(loseType);
|
generic(loseType);
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSetGeneric2() {
|
void testSetGeneric2() {
|
||||||
void generic<T extends Object>(T arg) {
|
void generic<T extends Object>(T arg) {
|
||||||
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
Pointer<Int8> p = Pointer.allocate();
|
||||||
p.store(arg); //# 27: compile-time error
|
p.value = arg; //# 27: compile-time error
|
||||||
p.free();
|
p.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,33 +128,33 @@ void testSetGeneric2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSetVoid() {
|
void testSetVoid() {
|
||||||
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
|
Pointer<IntPtr> p1 = Pointer.allocate();
|
||||||
ffi.Pointer<ffi.Void> p2 = p1.cast();
|
Pointer<Void> p2 = p1.cast();
|
||||||
|
|
||||||
p2.store(1234); //# 28: compile-time error
|
p2.value = 1234; //# 28: compile-time error
|
||||||
|
|
||||||
p1.free();
|
p1.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSetNativeFunction() {
|
void testSetNativeFunction() {
|
||||||
Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
||||||
IntUnOp f = (a) => a + 1;
|
IntUnOp f = (a) => a + 1;
|
||||||
p.store(f); //# 29: compile-time error
|
p.value = f; //# 29: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSetNativeType() {
|
void testSetNativeType() {
|
||||||
// Is it possible to obtain a ffi.Pointer<ffi.NativeType> at all?
|
// Is it possible to obtain a Pointer<NativeType> at all?
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSetTypeMismatch() {
|
void testSetTypeMismatch() {
|
||||||
// the pointer to pointer types must match up
|
// the pointer to pointer types must match up
|
||||||
ffi.Pointer<ffi.Int8> pHelper = Pointer.allocate();
|
Pointer<Int8> pHelper = Pointer.allocate();
|
||||||
pHelper.store(123);
|
pHelper.value = 123;
|
||||||
|
|
||||||
ffi.Pointer<ffi.Pointer<ffi.Int16>> p = Pointer.allocate();
|
Pointer<Pointer<Int16>> p = Pointer.allocate();
|
||||||
|
|
||||||
// this fails to compile due to type mismatch
|
// this fails to compile due to type mismatch
|
||||||
p.store(pHelper); //# 40: compile-time error
|
p.value = pHelper; //# 40: compile-time error
|
||||||
|
|
||||||
pHelper.free();
|
pHelper.free();
|
||||||
p.free();
|
p.free();
|
||||||
|
@ -163,7 +162,7 @@ void testSetTypeMismatch() {
|
||||||
|
|
||||||
void testAsFunctionGeneric() {
|
void testAsFunctionGeneric() {
|
||||||
T generic<T extends Function>() {
|
T generic<T extends Function>() {
|
||||||
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
||||||
Function f;
|
Function f;
|
||||||
f = p.asFunction<T>(); //# 11: compile-time error
|
f = p.asFunction<T>(); //# 11: compile-time error
|
||||||
return f;
|
return f;
|
||||||
|
@ -173,29 +172,29 @@ void testAsFunctionGeneric() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAsFunctionGeneric2() {
|
void testAsFunctionGeneric2() {
|
||||||
generic(ffi.Pointer<ffi.NativeFunction> p) {
|
generic(Pointer<NativeFunction> p) {
|
||||||
Function f;
|
Function f;
|
||||||
f = p.asFunction<IntUnOp>(); //# 12: compile-time error
|
f = p.asFunction<IntUnOp>(); //# 12: compile-time error
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
||||||
generic(p);
|
generic(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAsFunctionWrongNativeFunctionSignature() {
|
void testAsFunctionWrongNativeFunctionSignature() {
|
||||||
ffi.Pointer<ffi.NativeFunction<IntUnOp>> p;
|
Pointer<NativeFunction<IntUnOp>> p;
|
||||||
Function f = p.asFunction<IntUnOp>(); //# 13: compile-time error
|
Function f = p.asFunction<IntUnOp>(); //# 13: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef IntBinOp = int Function(int, int);
|
typedef IntBinOp = int Function(int, int);
|
||||||
|
|
||||||
void testAsFunctionTypeMismatch() {
|
void testAsFunctionTypeMismatch() {
|
||||||
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
||||||
IntBinOp f = p.asFunction(); //# 14: compile-time error
|
IntBinOp f = p.asFunction(); //# 14: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double);
|
typedef NativeDoubleUnOp = Double Function(Double);
|
||||||
typedef DoubleUnOp = double Function(double);
|
typedef DoubleUnOp = double Function(double);
|
||||||
|
|
||||||
double myTimesThree(double d) => d * 3;
|
double myTimesThree(double d) => d * 3;
|
||||||
|
@ -203,9 +202,9 @@ double myTimesThree(double d) => d * 3;
|
||||||
int myTimesFour(int i) => i * 4;
|
int myTimesFour(int i) => i * 4;
|
||||||
|
|
||||||
void testFromFunctionGeneric() {
|
void testFromFunctionGeneric() {
|
||||||
ffi.Pointer<ffi.NativeFunction> generic<T extends Function>(T f) {
|
Pointer<NativeFunction> generic<T extends Function>(T f) {
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> result;
|
Pointer<NativeFunction<NativeDoubleUnOp>> result;
|
||||||
result = ffi.fromFunction(f); //# 70: compile-time error
|
result = Pointer.fromFunction(f); //# 70: compile-time error
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,9 +212,9 @@ void testFromFunctionGeneric() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFromFunctionGeneric2() {
|
void testFromFunctionGeneric2() {
|
||||||
ffi.Pointer<ffi.NativeFunction<T>> generic<T extends Function>() {
|
Pointer<NativeFunction<T>> generic<T extends Function>() {
|
||||||
ffi.Pointer<ffi.NativeFunction<T>> result;
|
Pointer<NativeFunction<T>> result;
|
||||||
result = ffi.fromFunction(myTimesThree); //# 71: compile-time error
|
result = Pointer.fromFunction(myTimesThree); //# 71: compile-time error
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,18 +222,18 @@ void testFromFunctionGeneric2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFromFunctionWrongNativeFunctionSignature() {
|
void testFromFunctionWrongNativeFunctionSignature() {
|
||||||
ffi.fromFunction<IntUnOp>(myTimesFour); //# 72: compile-time error
|
Pointer.fromFunction<IntUnOp>(myTimesFour); //# 72: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFromFunctionTypeMismatch() {
|
void testFromFunctionTypeMismatch() {
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
|
Pointer<NativeFunction<NativeDoubleUnOp>> p;
|
||||||
p = ffi.fromFunction(myTimesFour); //# 73: compile-time error
|
p = Pointer.fromFunction(myTimesFour); //# 73: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFromFunctionClosure() {
|
void testFromFunctionClosure() {
|
||||||
DoubleUnOp someClosure = (double z) => z / 27.0;
|
DoubleUnOp someClosure = (double z) => z / 27.0;
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
|
Pointer<NativeFunction<NativeDoubleUnOp>> p;
|
||||||
p = ffi.fromFunction(someClosure); //# 74: compile-time error
|
p = Pointer.fromFunction(someClosure); //# 74: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
class X {
|
class X {
|
||||||
|
@ -245,17 +244,18 @@ DoubleUnOp fld = null;
|
||||||
|
|
||||||
void testFromFunctionTearOff() {
|
void testFromFunctionTearOff() {
|
||||||
fld = X().tearoff;
|
fld = X().tearoff;
|
||||||
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
|
Pointer<NativeFunction<NativeDoubleUnOp>> p;
|
||||||
p = ffi.fromFunction(fld); //# 75: compile-time error
|
p = Pointer.fromFunction(fld); //# 75: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFromFunctionAbstract() {
|
void testFromFunctionAbstract() {
|
||||||
ffi.Pointer.fromFunction<Function>(testFromFunctionAbstract); //# 76: compile-time error
|
Pointer.fromFunction<Function>(//# 76: compile-time error
|
||||||
|
testFromFunctionAbstract); //# 76: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
void testLookupFunctionGeneric() {
|
void testLookupFunctionGeneric() {
|
||||||
Function generic<T extends Function>() {
|
Function generic<T extends Function>() {
|
||||||
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
||||||
Function result;
|
Function result;
|
||||||
result = l.lookupFunction<T, DoubleUnOp>("cos"); //# 15: compile-time error
|
result = l.lookupFunction<T, DoubleUnOp>("cos"); //# 15: compile-time error
|
||||||
return result;
|
return result;
|
||||||
|
@ -266,7 +266,7 @@ void testLookupFunctionGeneric() {
|
||||||
|
|
||||||
void testLookupFunctionGeneric2() {
|
void testLookupFunctionGeneric2() {
|
||||||
Function generic<T extends Function>() {
|
Function generic<T extends Function>() {
|
||||||
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
||||||
Function result;
|
Function result;
|
||||||
result = //# 16: compile-time error
|
result = //# 16: compile-time error
|
||||||
l.lookupFunction<NativeDoubleUnOp, T>("cos"); //# 16: compile-time error
|
l.lookupFunction<NativeDoubleUnOp, T>("cos"); //# 16: compile-time error
|
||||||
|
@ -277,40 +277,40 @@ void testLookupFunctionGeneric2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testLookupFunctionWrongNativeFunctionSignature() {
|
void testLookupFunctionWrongNativeFunctionSignature() {
|
||||||
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
||||||
l.lookupFunction<IntUnOp, IntUnOp>("cos"); //# 17: compile-time error
|
l.lookupFunction<IntUnOp, IntUnOp>("cos"); //# 17: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
void testLookupFunctionTypeMismatch() {
|
void testLookupFunctionTypeMismatch() {
|
||||||
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
||||||
l.lookupFunction<NativeDoubleUnOp, IntUnOp>("cos"); //# 18: compile-time error
|
l.lookupFunction<NativeDoubleUnOp, IntUnOp>("cos"); //# 18: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dacoharkes): make the next 4 test compile errors
|
// TODO(dacoharkes): make the next 4 test compile errors
|
||||||
typedef Invalid1 = int Function(ffi.Int8);
|
typedef Invalid1 = int Function(Int8);
|
||||||
typedef Invalid2 = ffi.Int8 Function(int);
|
typedef Invalid2 = Int8 Function(int);
|
||||||
typedef Invalid3 = ffi.Int8 Function({ffi.Int8 named});
|
typedef Invalid3 = Int8 Function({Int8 named});
|
||||||
typedef Invalid4 = ffi.Int8 Function([ffi.Int8 positional]);
|
typedef Invalid4 = Int8 Function([Int8 positional]);
|
||||||
|
|
||||||
void testNativeFunctionSignatureInvalidReturn() {
|
void testNativeFunctionSignatureInvalidReturn() {
|
||||||
// ffi.Pointer<ffi.NativeFunction<Invalid1>> p = ffi.fromAddress(999);
|
// Pointer<NativeFunction<Invalid1>> p = fromAddress(999);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testNativeFunctionSignatureInvalidParam() {
|
void testNativeFunctionSignatureInvalidParam() {
|
||||||
// ffi.Pointer<ffi.NativeFunction<Invalid2>> p = ffi.fromAddress(999);
|
// Pointer<NativeFunction<Invalid2>> p = fromAddress(999);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testNativeFunctionSignatureInvalidOptionalNamed() {
|
void testNativeFunctionSignatureInvalidOptionalNamed() {
|
||||||
// ffi.Pointer<ffi.NativeFunction<Invalid3>> p = ffi.fromAddress(999);
|
// Pointer<NativeFunction<Invalid3>> p = fromAddress(999);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testNativeFunctionSignatureInvalidOptionalPositional() {
|
void testNativeFunctionSignatureInvalidOptionalPositional() {
|
||||||
// ffi.Pointer<ffi.NativeFunction<Invalid4>> p = ffi.fromAddress(999);
|
// Pointer<NativeFunction<Invalid4>> p = fromAddress(999);
|
||||||
}
|
}
|
||||||
|
|
||||||
// error on missing field annotation
|
// error on missing field annotation
|
||||||
class TestStruct extends ffi.Struct<TestStruct> {
|
class TestStruct extends Struct<TestStruct> {
|
||||||
@ffi.Double()
|
@Double()
|
||||||
double x;
|
double x;
|
||||||
|
|
||||||
double y; //# 50: compile-time error
|
double y; //# 50: compile-time error
|
||||||
|
@ -320,55 +320,55 @@ class TestStruct extends ffi.Struct<TestStruct> {
|
||||||
class TestStruct3 extends TestStruct {} //# 52: compile-time error
|
class TestStruct3 extends TestStruct {} //# 52: compile-time error
|
||||||
|
|
||||||
// error on double annotation
|
// error on double annotation
|
||||||
class TestStruct4 extends ffi.Struct<TestStruct4> {
|
class TestStruct4 extends Struct<TestStruct4> {
|
||||||
@ffi.Double()
|
@Double()
|
||||||
@ffi.Double() //# 53: compile-time error
|
@Double() //# 53: compile-time error
|
||||||
double z;
|
double z;
|
||||||
}
|
}
|
||||||
|
|
||||||
// error on annotation not matching up
|
// error on annotation not matching up
|
||||||
class TestStruct5 extends ffi.Struct<TestStruct5> {
|
class TestStruct5 extends Struct<TestStruct5> {
|
||||||
@ffi.Int64() //# 54: compile-time error
|
@Int64() //# 54: compile-time error
|
||||||
double z; //# 54: compile-time error
|
double z; //# 54: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
// error on annotation not matching up
|
// error on annotation not matching up
|
||||||
class TestStruct6 extends ffi.Struct<TestStruct6> {
|
class TestStruct6 extends Struct<TestStruct6> {
|
||||||
@ffi.Void() //# 55: compile-time error
|
@Void() //# 55: compile-time error
|
||||||
double z; //# 55: compile-time error
|
double z; //# 55: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
// error on annotation not matching up
|
// error on annotation not matching up
|
||||||
class TestStruct7 extends ffi.Struct<TestStruct7> {
|
class TestStruct7 extends Struct<TestStruct7> {
|
||||||
@ffi.NativeType() //# 56: compile-time error
|
@NativeType() //# 56: compile-time error
|
||||||
double z; //# 56: compile-time error
|
double z; //# 56: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
// error on field initializer on field
|
// error on field initializer on field
|
||||||
class TestStruct8 extends ffi.Struct<TestStruct8> {
|
class TestStruct8 extends Struct<TestStruct8> {
|
||||||
@ffi.Double() //# 57: compile-time error
|
@Double() //# 57: compile-time error
|
||||||
double z = 10.0; //# 57: compile-time error
|
double z = 10.0; //# 57: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
// error on field initializer in constructor
|
// error on field initializer in constructor
|
||||||
class TestStruct9 extends ffi.Struct<TestStruct9> {
|
class TestStruct9 extends Struct<TestStruct9> {
|
||||||
@ffi.Double()
|
@Double()
|
||||||
double z;
|
double z;
|
||||||
|
|
||||||
TestStruct9() : z = 0.0 {} //# 58: compile-time error
|
TestStruct9() : z = 0.0 {} //# 58: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
// A struct "C" must extend "Struct<C>", not "Struct<AnythingElse>".
|
// A struct "C" must extend "Struct<C>", not "Struct<AnythingElse>".
|
||||||
class TestStruct10 extends ffi.Struct<ffi.Int8> {} //# 59: compile-time error
|
class TestStruct10 extends Struct<Int8> {} //# 59: compile-time error
|
||||||
|
|
||||||
// Struct classes may not be generic.
|
// Struct classes may not be generic.
|
||||||
class TestStruct11<T> extends //# 60: compile-time error
|
class TestStruct11<T> extends //# 60: compile-time error
|
||||||
ffi.Struct<TestStruct11<dynamic>> {} //# 60: compile-time error
|
Struct<TestStruct11<dynamic>> {} //# 60: compile-time error
|
||||||
|
|
||||||
// Structs may not appear inside structs (currently, there is no suitable
|
// Structs may not appear inside structs (currently, there is no suitable
|
||||||
// annotation).
|
// annotation).
|
||||||
class TestStruct12 extends ffi.Struct<TestStruct12> {
|
class TestStruct12 extends Struct<TestStruct12> {
|
||||||
@ffi.Pointer //# 61: compile-time error
|
@Pointer //# 61: compile-time error
|
||||||
TestStruct9 struct; //# 61: compile-time error
|
TestStruct9 struct; //# 61: compile-time error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,78 +377,78 @@ class DummyAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Structs fields may have other annotations.
|
// Structs fields may have other annotations.
|
||||||
class TestStruct13 extends ffi.Struct<TestStruct13> {
|
class TestStruct13 extends Struct<TestStruct13> {
|
||||||
@DummyAnnotation()
|
@DummyAnnotation()
|
||||||
@ffi.Double()
|
@Double()
|
||||||
double z;
|
double z;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot extend native types.
|
// Cannot extend native types.
|
||||||
|
|
||||||
class ENativeType extends ffi.NativeType {} //# 90: compile-time error
|
class ENativeType extends NativeType {} //# 90: compile-time error
|
||||||
|
|
||||||
class EInt8 extends ffi.Int8 {} //# 91: compile-time error
|
class EInt8 extends Int8 {} //# 91: compile-time error
|
||||||
|
|
||||||
class EInt16 extends ffi.Int16 {} //# 92: compile-time error
|
class EInt16 extends Int16 {} //# 92: compile-time error
|
||||||
|
|
||||||
class EInt32 extends ffi.Int32 {} //# 93: compile-time error
|
class EInt32 extends Int32 {} //# 93: compile-time error
|
||||||
|
|
||||||
class EInt64 extends ffi.Int64 {} //# 94: compile-time error
|
class EInt64 extends Int64 {} //# 94: compile-time error
|
||||||
|
|
||||||
class EUint8 extends ffi.Uint8 {} //# 95: compile-time error
|
class EUint8 extends Uint8 {} //# 95: compile-time error
|
||||||
|
|
||||||
class EUint16 extends ffi.Uint16 {} //# 96: compile-time error
|
class EUint16 extends Uint16 {} //# 96: compile-time error
|
||||||
|
|
||||||
class EUint32 extends ffi.Uint32 {} //# 97: compile-time error
|
class EUint32 extends Uint32 {} //# 97: compile-time error
|
||||||
|
|
||||||
class EUint64 extends ffi.Uint64 {} //# 98: compile-time error
|
class EUint64 extends Uint64 {} //# 98: compile-time error
|
||||||
|
|
||||||
class EIntPtr extends ffi.IntPtr {} //# 99: compile-time error
|
class EIntPtr extends IntPtr {} //# 99: compile-time error
|
||||||
|
|
||||||
class EFloat extends ffi.Float {} //# 910: compile-time error
|
class EFloat extends Float {} //# 910: compile-time error
|
||||||
|
|
||||||
class EDouble extends ffi.Double {} //# 911: compile-time error
|
class EDouble extends Double {} //# 911: compile-time error
|
||||||
|
|
||||||
class EVoid extends ffi.Void {} //# 912: compile-time error
|
class EVoid extends Void {} //# 912: compile-time error
|
||||||
|
|
||||||
class ENativeFunction extends ffi.NativeFunction {} //# 913: compile-time error
|
class ENativeFunction extends NativeFunction {} //# 913: compile-time error
|
||||||
|
|
||||||
class EPointer extends ffi.Pointer {} //# 914: compile-time error
|
class EPointer extends Pointer {} //# 914: compile-time error
|
||||||
|
|
||||||
// Cannot implement native natives or Struct.
|
// Cannot implement native natives or Struct.
|
||||||
|
|
||||||
// Cannot extend native types.
|
// Cannot extend native types.
|
||||||
|
|
||||||
class INativeType implements ffi.NativeType {} //# 80: compile-time error
|
class INativeType implements NativeType {} //# 80: compile-time error
|
||||||
|
|
||||||
class IInt8 implements ffi.Int8 {} //# 81: compile-time error
|
class IInt8 implements Int8 {} //# 81: compile-time error
|
||||||
|
|
||||||
class IInt16 implements ffi.Int16 {} //# 82: compile-time error
|
class IInt16 implements Int16 {} //# 82: compile-time error
|
||||||
|
|
||||||
class IInt32 implements ffi.Int32 {} //# 83: compile-time error
|
class IInt32 implements Int32 {} //# 83: compile-time error
|
||||||
|
|
||||||
class IInt64 implements ffi.Int64 {} //# 84: compile-time error
|
class IInt64 implements Int64 {} //# 84: compile-time error
|
||||||
|
|
||||||
class IUint8 implements ffi.Uint8 {} //# 85: compile-time error
|
class IUint8 implements Uint8 {} //# 85: compile-time error
|
||||||
|
|
||||||
class IUint16 implements ffi.Uint16 {} //# 86: compile-time error
|
class IUint16 implements Uint16 {} //# 86: compile-time error
|
||||||
|
|
||||||
class IUint32 implements ffi.Uint32 {} //# 87: compile-time error
|
class IUint32 implements Uint32 {} //# 87: compile-time error
|
||||||
|
|
||||||
class IUint64 implements ffi.Uint64 {} //# 88: compile-time error
|
class IUint64 implements Uint64 {} //# 88: compile-time error
|
||||||
|
|
||||||
class IIntPtr implements ffi.IntPtr {} //# 88: compile-time error
|
class IIntPtr implements IntPtr {} //# 88: compile-time error
|
||||||
|
|
||||||
class IFloat implements ffi.Float {} //# 810: compile-time error
|
class IFloat implements Float {} //# 810: compile-time error
|
||||||
|
|
||||||
class IDouble implements ffi.Double {} //# 811: compile-time error
|
class IDouble implements Double {} //# 811: compile-time error
|
||||||
|
|
||||||
class IVoid implements ffi.Void {} //# 812: compile-time error
|
class IVoid implements Void {} //# 812: compile-time error
|
||||||
|
|
||||||
class INativeFunction //# 813: compile-time error
|
class INativeFunction //# 813: compile-time error
|
||||||
implements //# 813: compile-time error
|
implements //# 813: compile-time error
|
||||||
ffi.NativeFunction {} //# 813: compile-time error
|
NativeFunction {} //# 813: compile-time error
|
||||||
|
|
||||||
class IPointer implements ffi.Pointer {} //# 814: compile-time error
|
class IPointer implements Pointer {} //# 814: compile-time error
|
||||||
|
|
||||||
class IStruct implements ffi.Struct {} //# 815: compile-time error
|
class IStruct implements Struct {} //# 815: compile-time error
|
||||||
|
|
|
@ -33,15 +33,15 @@ void testStructAllocate() {
|
||||||
Coordinate.allocate(10.0, 10.0, nullptr.cast()).addressOf;
|
Coordinate.allocate(10.0, 10.0, nullptr.cast()).addressOf;
|
||||||
Pointer<Coordinate> c2 = Coordinate.allocate(20.0, 20.0, c1).addressOf;
|
Pointer<Coordinate> c2 = Coordinate.allocate(20.0, 20.0, c1).addressOf;
|
||||||
Pointer<Coordinate> c3 = Coordinate.allocate(30.0, 30.0, c2).addressOf;
|
Pointer<Coordinate> c3 = Coordinate.allocate(30.0, 30.0, c2).addressOf;
|
||||||
c1.load<Coordinate>().next = c3;
|
c1.ref.next = c3;
|
||||||
|
|
||||||
Coordinate currentCoordinate = c1.load();
|
Coordinate currentCoordinate = c1.ref;
|
||||||
Expect.equals(10.0, currentCoordinate.x);
|
Expect.equals(10.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(30.0, currentCoordinate.x);
|
Expect.equals(30.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(20.0, currentCoordinate.x);
|
Expect.equals(20.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(10.0, currentCoordinate.x);
|
Expect.equals(10.0, currentCoordinate.x);
|
||||||
|
|
||||||
c1.free();
|
c1.free();
|
||||||
|
@ -54,23 +54,26 @@ void testStructFromAddress() {
|
||||||
Pointer<Coordinate> c1 = Pointer.allocate(count: 3);
|
Pointer<Coordinate> c1 = Pointer.allocate(count: 3);
|
||||||
Pointer<Coordinate> c2 = c1.elementAt(1);
|
Pointer<Coordinate> c2 = c1.elementAt(1);
|
||||||
Pointer<Coordinate> c3 = c1.elementAt(2);
|
Pointer<Coordinate> c3 = c1.elementAt(2);
|
||||||
c1.load<Coordinate>().x = 10.0;
|
c1.ref
|
||||||
c1.load<Coordinate>().y = 10.0;
|
..x = 10.0
|
||||||
c1.load<Coordinate>().next = c3;
|
..y = 10.0
|
||||||
c2.load<Coordinate>().x = 20.0;
|
..next = c3;
|
||||||
c2.load<Coordinate>().y = 20.0;
|
c2.ref
|
||||||
c2.load<Coordinate>().next = c1;
|
..x = 20.0
|
||||||
c3.load<Coordinate>().x = 30.0;
|
..y = 20.0
|
||||||
c3.load<Coordinate>().y = 30.0;
|
..next = c1;
|
||||||
c3.load<Coordinate>().next = c2;
|
c3.ref
|
||||||
|
..x = 30.0
|
||||||
|
..y = 30.0
|
||||||
|
..next = c2;
|
||||||
|
|
||||||
Coordinate currentCoordinate = c1.load();
|
Coordinate currentCoordinate = c1.ref;
|
||||||
Expect.equals(10.0, currentCoordinate.x);
|
Expect.equals(10.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(30.0, currentCoordinate.x);
|
Expect.equals(30.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(20.0, currentCoordinate.x);
|
Expect.equals(20.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(10.0, currentCoordinate.x);
|
Expect.equals(10.0, currentCoordinate.x);
|
||||||
|
|
||||||
c1.free();
|
c1.free();
|
||||||
|
@ -79,11 +82,11 @@ void testStructFromAddress() {
|
||||||
void testStructWithNulls() {
|
void testStructWithNulls() {
|
||||||
Pointer<Coordinate> coordinate =
|
Pointer<Coordinate> coordinate =
|
||||||
Coordinate.allocate(10.0, 10.0, nullptr.cast<Coordinate>()).addressOf;
|
Coordinate.allocate(10.0, 10.0, nullptr.cast<Coordinate>()).addressOf;
|
||||||
Expect.equals(coordinate.load<Coordinate>().next, nullptr);
|
Expect.equals(coordinate.ref.next, nullptr);
|
||||||
coordinate.load<Coordinate>().next = coordinate;
|
coordinate.ref.next = coordinate;
|
||||||
Expect.notEquals(coordinate.load<Coordinate>().next, nullptr);
|
Expect.notEquals(coordinate.ref.next, nullptr);
|
||||||
coordinate.load<Coordinate>().next = nullptr.cast();
|
coordinate.ref.next = nullptr.cast();
|
||||||
Expect.equals(coordinate.load<Coordinate>().next, nullptr);
|
Expect.equals(coordinate.ref.next, nullptr);
|
||||||
coordinate.free();
|
coordinate.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,11 +94,11 @@ void testBareStruct() {
|
||||||
int structSize = sizeOf<Double>() * 2 + sizeOf<IntPtr>();
|
int structSize = sizeOf<Double>() * 2 + sizeOf<IntPtr>();
|
||||||
bare.Coordinate c1 = Pointer<Uint8>.allocate(count: structSize * 3)
|
bare.Coordinate c1 = Pointer<Uint8>.allocate(count: structSize * 3)
|
||||||
.cast<bare.Coordinate>()
|
.cast<bare.Coordinate>()
|
||||||
.load();
|
.ref;
|
||||||
bare.Coordinate c2 =
|
bare.Coordinate c2 =
|
||||||
c1.addressOf.offsetBy(structSize).cast<bare.Coordinate>().load();
|
c1.addressOf.offsetBy(structSize).cast<bare.Coordinate>().ref;
|
||||||
bare.Coordinate c3 =
|
bare.Coordinate c3 =
|
||||||
c1.addressOf.offsetBy(structSize * 2).cast<bare.Coordinate>().load();
|
c1.addressOf.offsetBy(structSize * 2).cast<bare.Coordinate>().ref;
|
||||||
c1.x = 10.0;
|
c1.x = 10.0;
|
||||||
c1.y = 10.0;
|
c1.y = 10.0;
|
||||||
c1.next = c3.addressOf;
|
c1.next = c3.addressOf;
|
||||||
|
@ -108,11 +111,11 @@ void testBareStruct() {
|
||||||
|
|
||||||
bare.Coordinate currentCoordinate = c1;
|
bare.Coordinate currentCoordinate = c1;
|
||||||
Expect.equals(10.0, currentCoordinate.x);
|
Expect.equals(10.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(30.0, currentCoordinate.x);
|
Expect.equals(30.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(20.0, currentCoordinate.x);
|
Expect.equals(20.0, currentCoordinate.x);
|
||||||
currentCoordinate = currentCoordinate.next.load();
|
currentCoordinate = currentCoordinate.next.ref;
|
||||||
Expect.equals(10.0, currentCoordinate.x);
|
Expect.equals(10.0, currentCoordinate.x);
|
||||||
|
|
||||||
c1.addressOf.free();
|
c1.addressOf.free();
|
||||||
|
|
|
@ -5,19 +5,18 @@
|
||||||
library Utf8;
|
library Utf8;
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:ffi' as ffi;
|
import 'dart:ffi';
|
||||||
import 'dart:ffi' show Pointer;
|
|
||||||
|
|
||||||
/// Sample non-struct Pointer wrapper for dart:ffi library.
|
/// Sample non-struct Pointer wrapper for dart:ffi library.
|
||||||
class Utf8 extends ffi.Struct<Utf8> {
|
class Utf8 extends Struct<Utf8> {
|
||||||
@ffi.Uint8()
|
@Uint8()
|
||||||
int char;
|
int char;
|
||||||
|
|
||||||
static String fromUtf8(Pointer<Utf8> str) {
|
static String fromUtf8(Pointer<Utf8> str) {
|
||||||
List<int> units = [];
|
List<int> units = [];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
int char = str.elementAt(len++).load<Utf8>().char;
|
int char = str[len++].char;
|
||||||
if (char == 0) break;
|
if (char == 0) break;
|
||||||
units.add(char);
|
units.add(char);
|
||||||
}
|
}
|
||||||
|
@ -29,9 +28,9 @@ class Utf8 extends ffi.Struct<Utf8> {
|
||||||
Pointer<Utf8> result =
|
Pointer<Utf8> result =
|
||||||
Pointer<Utf8>.allocate(count: units.length + 1).cast();
|
Pointer<Utf8>.allocate(count: units.length + 1).cast();
|
||||||
for (int i = 0; i < units.length; i++) {
|
for (int i = 0; i < units.length; i++) {
|
||||||
result.elementAt(i).load<Utf8>().char = units[i];
|
result[i].char = units[i];
|
||||||
}
|
}
|
||||||
result.elementAt(units.length).load<Utf8>().char = 0;
|
result[units.length].char = 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue