1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-05 09:20:04 +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:
Daco Harkes 2019-10-08 16:49:41 +00:00 committed by commit-bot@chromium.org
parent 597cd06aec
commit ee0b1df4a6
20 changed files with 653 additions and 682 deletions

View File

@ -29,7 +29,7 @@ Uint8List toUint8List(Bytes bytes, int length) {
final result = Uint8List(length);
final uint8bytes = bytes.asUint8Pointer();
for (int i = 0; i < length; i++) {
result[i] = uint8bytes.elementAt(i).load<int>();
result[i] = uint8bytes[i];
}
return result;
}
@ -38,7 +38,7 @@ void copyFromUint8ListToTarget(Uint8List source, Data target) {
final int length = source.length;
final uint8target = target.asUint8Pointer();
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();
EVP_DigestFinal(context, result, nullptr.cast());
EVP_MD_CTX_free(context);
final String hash = base64Encode(toUint8List(result.load(), resultSize));
final String hash = base64Encode(toUint8List(result.ref, resultSize));
result.free();
return hash;
}
@ -86,7 +86,7 @@ class DigestCMemory extends BenchmarkBase {
void setup() {
data = Pointer<Uint8>.allocate(count: L).cast();
copyFromUint8ListToTarget(inventData(L), data.load());
copyFromUint8ListToTarget(inventData(L), data.ref);
hash(data, L, hashAlgorithm);
}
@ -113,7 +113,7 @@ class DigestDartMemory extends BenchmarkBase {
void setup() {
data = inventData(L);
final Pointer<Data> dataInC = Pointer<Uint8>.allocate(count: L).cast();
copyFromUint8ListToTarget(data, dataInC.load());
copyFromUint8ListToTarget(data, dataInC.ref);
hash(dataInC, L, hashAlgorithm);
dataInC.free();
}
@ -122,7 +122,7 @@ class DigestDartMemory extends BenchmarkBase {
void run() {
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);
dataInC.free();
if (result != expectedHash) {

View File

@ -12,14 +12,14 @@ class EVP_MD_CTX extends Struct<EVP_MD_CTX> {}
/// Type for `void*` used to represent opaque 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();
}
/// Type for `uint8_t*` used to represent byte data.
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();
}

View File

@ -19,74 +19,74 @@ import 'package:benchmark_harness/benchmark_harness.dart';
void doStoreInt8(Pointer<Int8> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreUint8(Pointer<Uint8> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreInt16(Pointer<Int16> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreUint16(Pointer<Uint16> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreInt32(Pointer<Int32> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreUint32(Pointer<Uint32> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreInt64(Pointer<Int64> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreUint64(Pointer<Uint64> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1);
pointer[i] = 1;
}
}
void doStoreFloat(Pointer<Float> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1.0);
pointer[i] = 1.0;
}
}
void doStoreDouble(Pointer<Double> pointer, int length) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(1.0);
pointer[i] = 1.0;
}
}
void doStorePointer(
Pointer<Pointer<Int8>> pointer, int length, Pointer<Int8> data) {
for (int i = 0; i < length; i++) {
pointer.elementAt(i).store(data);
pointer[i] = data;
}
}
void doStoreInt64Mint(Pointer<Int64> pointer, int length) {
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 x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -105,7 +105,7 @@ int doLoadInt8(Pointer<Int8> pointer, int length) {
int doLoadUint8(Pointer<Uint8> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -113,7 +113,7 @@ int doLoadUint8(Pointer<Uint8> pointer, int length) {
int doLoadInt16(Pointer<Int16> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -121,7 +121,7 @@ int doLoadInt16(Pointer<Int16> pointer, int length) {
int doLoadUint16(Pointer<Uint16> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -129,7 +129,7 @@ int doLoadUint16(Pointer<Uint16> pointer, int length) {
int doLoadInt32(Pointer<Int32> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -137,7 +137,7 @@ int doLoadInt32(Pointer<Int32> pointer, int length) {
int doLoadUint32(Pointer<Uint32> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -145,7 +145,7 @@ int doLoadUint32(Pointer<Uint32> pointer, int length) {
int doLoadInt64(Pointer<Int64> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -153,7 +153,7 @@ int doLoadInt64(Pointer<Int64> pointer, int length) {
int doLoadUint64(Pointer<Uint64> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}
@ -161,7 +161,7 @@ int doLoadUint64(Pointer<Uint64> pointer, int length) {
double doLoadFloat(Pointer<Float> pointer, int length) {
double x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<double>();
x += pointer[i];
}
return x;
}
@ -169,7 +169,7 @@ double doLoadFloat(Pointer<Float> pointer, int length) {
double doLoadDouble(Pointer<Double> pointer, int length) {
double x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<double>();
x += pointer[i];
}
return x;
}
@ -179,7 +179,7 @@ int doLoadPointer(Pointer<Pointer<Int8>> pointer, int length) {
Pointer<Int8> x;
int address_xor = 0;
for (int i = 0; i < length; i++) {
x = pointer.elementAt(i).load();
x = pointer[i];
address_xor ^= x.address;
}
return address_xor;
@ -188,7 +188,7 @@ int doLoadPointer(Pointer<Pointer<Int8>> pointer, int length) {
int doLoadInt64Mint(Pointer<Int64> pointer, int length) {
int x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<int>();
x += pointer[i];
}
return x;
}

View File

@ -17,7 +17,7 @@ import 'package:benchmark_harness/benchmark_harness.dart';
void doStoreInt32(Pointer<VeryLargeStruct> pointer, int length) {
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 x = 0;
for (int i = 0; i < length; i++) {
x += pointer.elementAt(i).load<VeryLargeStruct>().c;
x += pointer[i].c;
}
return x;
}

View File

@ -79,8 +79,8 @@ However, before we can write to C memory from dart, we need to `allocate` some m
```dart
Pointer<Uint8> p = allocate(); // Infers type argument allocate<Uint8>(), and allocates 1 byte.
p.store(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.
p.value = 123; // Stores a Dart int into this C int8.
int v = p.value; // Loads a value from C memory.
```
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
CString string = allocate(count: 4).cast(); // Allocates 4 bytes and casts it to a string.
string.store(73); // Stores 'F' at index 0.
string.elementAt(1).store(73); // Stores 'F' at index 1.
string.elementAt(2).store(70); // Stores 'I' at index 2.
string.elementAt(3).store(0); // Null terminates the string.
string.value = 73; // Stores 'F' at index 0.
string[1] = 73; // Stores 'F' at index 1.
string[2] = 70; // Stores 'I' at index 2.
string[3] = 0; // Null terminates the string.
```
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.
```
StatementPointer statement = statementOut.load();
StatementPointer statement = statementOut.value;
statementOut.free();
queryC.free();
```

View File

@ -30,7 +30,7 @@ class Database {
final pathC = Utf8.allocate(path);
final int resultCode =
bindings.sqlite3_open_v2(pathC, dbOut, flags, Pointer.fromAddress(0));
_database = dbOut.load();
_database = dbOut.value;
dbOut.free();
pathC.free();
@ -66,7 +66,7 @@ class Database {
Pointer<Utf8> queryC = Utf8.allocate(query);
int resultCode = bindings.sqlite3_prepare_v2(
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
Pointer<Statement> statement = statementOut.load();
Pointer<Statement> statement = statementOut.value;
statementOut.free();
queryC.free();
@ -85,7 +85,7 @@ class Database {
Pointer<Utf8> queryC = Utf8.allocate(query);
int resultCode = bindings.sqlite3_prepare_v2(
_database, queryC, -1, statementOut, Pointer.fromAddress(0));
Pointer<Statement> statement = statementOut.load();
Pointer<Statement> statement = statementOut.value;
statementOut.free();
queryC.free();
@ -98,7 +98,7 @@ class Database {
int columnCount = bindings.sqlite3_column_count(statement);
for (int i = 0; i < columnCount; i++) {
String columnName =
bindings.sqlite3_column_name(statement, i).load<Utf8>().toString();
bindings.sqlite3_column_name(statement, i).ref.toString();
columnIndices[columnName] = i;
}
@ -106,13 +106,12 @@ class Database {
}
SQLiteException _loadError([int errorCode]) {
String errorMessage =
bindings.sqlite3_errmsg(_database).load<Utf8>().toString();
String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString();
if (errorCode == null) {
return SQLiteException(errorMessage);
}
String errorCodeExplanation =
bindings.sqlite3_errstr(errorCode).load<Utf8>().toString();
bindings.sqlite3_errstr(errorCode).ref.toString();
return SQLiteException(
"$errorMessage (Code $errorCode: $errorCodeExplanation)");
}
@ -214,7 +213,7 @@ class Row {
} else {
dynamicType = _typeFromText(bindings
.sqlite3_column_decltype(_statement, columnIndex)
.load<Utf8>()
.ref
.toString());
}
@ -251,10 +250,7 @@ class Row {
/// Reads column [columnIndex] and converts to [Type.Text] if not text.
String readColumnByIndexAsText(int columnIndex) {
_checkIsCurrentRow();
return bindings
.sqlite3_column_text(_statement, columnIndex)
.load<Utf8>()
.toString();
return bindings.sqlite3_column_text(_statement, columnIndex).ref.toString();
}
void _checkIsCurrentRow() {

View File

@ -29,9 +29,9 @@ class Utf8 extends Struct<Utf8> {
List<int> units = Utf8Encoder().convert(dartStr);
Pointer<Utf8> str = Pointer.allocate(count: units.length + 1);
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();
}
@ -40,9 +40,9 @@ class Utf8 extends Struct<Utf8> {
final str = addressOf;
if (str == nullptr) return null;
int len = 0;
while (str.elementAt(++len).load<Utf8>().char != 0);
while (str[++len].char != 0);
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);
}
}

View File

@ -4,6 +4,8 @@
// VMOptions=--optimization-counter-threshold=5
import 'dart:ffi';
import "package:test/test.dart";
import '../lib/sqlite.dart';
@ -11,6 +13,8 @@ import '../lib/src/ffi/utf8.dart';
void main() {
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");
d.execute("drop table if exists Cookies;");
d.execute("""
@ -165,7 +169,7 @@ void main() {
test("Utf8 unit test", () {
final String test = 'Hasta Mañana';
final medium = Utf8.allocate(test);
expect(test, medium.load<Utf8>().toString());
expect(test, medium.ref.toString());
medium.free();
});
}

View File

@ -37,22 +37,22 @@ void main() {
void testNonAlias() {
final source = Pointer<Int64>.allocate();
source.store(42);
final int a = source.load();
source.store(1984);
// alias.load() should be re-executed, as we wrote to alias.
Expect.notEquals(a, source.load<int>());
source.value = 42;
final int a = source.value;
source.value = 1984;
// alias.value should be re-executed, as we wrote to alias.
Expect.notEquals(a, source.value);
source.free();
}
void testAliasCast() {
final source = Pointer<Int64>.allocate();
final alias = source.cast<Int8>().cast<Int64>();
source.store(42);
final int a = source.load();
alias.store(1984);
// source.load() should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.load<int>());
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
}
@ -60,22 +60,22 @@ void testAliasCast2() {
final source = Pointer<Int64>.allocate();
final alias = source.cast<Int16>().cast<Int64>();
final alias2 = source.cast<Int8>().cast<Int64>();
alias.store(42);
final int a = alias.load();
alias2.store(1984);
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.load<int>());
alias.value = 42;
final int a = alias.value;
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
}
void testAliasOffsetBy() {
final source = Pointer<Int64>.allocate(count: 2);
final alias = source.offsetBy(8).offsetBy(-8);
source.store(42);
final int a = source.load();
alias.store(1984);
// source.load() should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.load<int>());
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
}
@ -83,22 +83,22 @@ void testAliasOffsetBy2() {
final source = Pointer<Int64>.allocate(count: 3);
final alias = source.offsetBy(16).offsetBy(-16);
final alias2 = source.offsetBy(8).offsetBy(-8);
alias.store(42);
final int a = alias.load();
alias2.store(1984);
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.load<int>());
alias.value = 42;
final int a = alias.value;
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
}
void testAliasElementAt() {
final source = Pointer<Int64>.allocate(count: 2);
final alias = source.elementAt(1).elementAt(-1);
source.store(42);
final int a = source.load();
alias.store(1984);
// source.load() should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.load<int>());
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
}
@ -106,22 +106,22 @@ void testAliasElementAt2() {
final source = Pointer<Int64>.allocate(count: 3);
final alias = source.elementAt(2).elementAt(-2);
final alias2 = source.elementAt(1).elementAt(-1);
alias.store(42);
final int a = alias.load();
alias2.store(1984);
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.load<int>());
alias.value = 42;
final int a = alias.value;
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
}
void testAliasFromAddress() {
final source = Pointer<Int64>.allocate();
final alias = Pointer<Int64>.fromAddress(source.address);
source.store(42);
final int a = source.load();
alias.store(1984);
// source.load() should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.load<int>());
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
}
@ -129,24 +129,24 @@ void testAliasFromAddress2() {
final source = Pointer<Int64>.allocate();
final alias = Pointer<Int64>.fromAddress(source.address);
final alias2 = Pointer<Int64>.fromAddress(source.address);
alias.store(42);
final int a = alias.load();
alias2.store(1984);
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.load<int>());
alias.value = 42;
final int a = alias.value;
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
}
void testAliasFromAddressViaMemory() {
final helper = Pointer<IntPtr>.allocate();
final source = Pointer<Int64>.allocate();
helper.store(source.address);
final alias = Pointer<Int64>.fromAddress(helper.load());
source.store(42);
final int a = source.load();
alias.store(1984);
// source.load() should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.load<int>());
helper.value = source.address;
final alias = Pointer<Int64>.fromAddress(helper.value);
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
helper.free();
source.free();
}
@ -154,14 +154,14 @@ void testAliasFromAddressViaMemory() {
void testAliasFromAddressViaMemory2() {
final helper = Pointer<IntPtr>.allocate();
final source = Pointer<Int64>.allocate();
helper.store(source.address);
final alias = Pointer<Int64>.fromAddress(helper.load());
final alias2 = Pointer<Int64>.fromAddress(helper.load());
alias.store(42);
final int a = alias.load();
alias2.store(1984);
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.load<int>());
helper.value = source.address;
final alias = Pointer<Int64>.fromAddress(helper.value);
final alias2 = Pointer<Int64>.fromAddress(helper.value);
alias.value = 42;
final int a = alias.value;
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
helper.free();
source.free();
}
@ -178,11 +178,11 @@ void testAliasFromAddressViaNativeFunction() {
final source = Pointer<Int64>.allocate();
final alias =
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
source.store(42);
final int a = source.load();
alias.store(1984);
// source.load() should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.load<int>());
source.value = 42;
final int a = source.value;
alias.value = 1984;
// source.value should be re-executed, we wrote alias which aliases source.
Expect.notEquals(a, source.value);
source.free();
}
@ -192,11 +192,11 @@ void testAliasFromAddressViaNativeFunction2() {
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
final alias2 =
Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
alias.store(42);
final int a = alias.load();
alias2.store(1984);
// alias.load() should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.load<int>());
alias.value = 42;
final int a = alias.value;
alias2.value = 1984;
// alias.value should be re-executed, we wrote alias2 which aliases alias.
Expect.notEquals(a, alias.value);
source.free();
}
@ -207,9 +207,9 @@ Pointer<Int8> makeDerived(Pointer<Int64> source) =>
testPartialOverlap() {
final source = Pointer<Int64>.allocate(count: 2);
final derived = makeDerived(source);
source.store(0x1122334455667788);
final int value = source.load();
derived.store(0xaa);
Expect.notEquals(value, source.load<int>());
source.value = 0x1122334455667788;
final int value = source.value;
derived.value = 0xaa;
Expect.notEquals(value, source.value);
source.free();
}

View File

@ -17,7 +17,7 @@ class Coordinate extends Struct<Coordinate> {
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
..y = y
..next = next;

View File

@ -9,8 +9,7 @@
library FfiTest;
import 'dart:ffi' as ffi;
import 'dart:ffi' show Pointer;
import 'dart:ffi';
import "package:expect/expect.dart";
@ -22,16 +21,16 @@ void main() {
void testPointerAllocateTooLarge() {
// Try to allocate something that doesn't fit in 64 bit address space.
int maxInt = 9223372036854775807; // 2^63 - 1
Expect.throws(() => Pointer<ffi.Int64>.allocate(count: maxInt));
Expect.throws(() => Pointer<Int64>.allocate(count: maxInt));
// Try to allocate almost the full 64 bit address space.
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() {
// Passing in -1 will be converted into an unsigned integer. So, it will try
// to allocate SIZE_MAX - 1 + 1 bytes. This will fail as it is the max amount
// of addressable memory on the system.
Expect.throws(() => Pointer<ffi.Int8>.allocate(count: -1));
Expect.throws(() => Pointer<Int8>.allocate(count: -1));
}

View File

@ -6,8 +6,7 @@
library FfiTest;
import 'dart:ffi' as ffi;
import 'dart:ffi' show Pointer;
import 'dart:ffi';
import "package:expect/expect.dart";
@ -55,39 +54,39 @@ void main() {
}
void testPointerBasic() {
Pointer<ffi.Int64> p = Pointer.allocate();
p.store(42);
Expect.equals(42, p.load<int>());
Pointer<Int64> p = Pointer.allocate();
p.value = 42;
Expect.equals(42, p.value);
p.free();
}
void testPointerFromPointer() {
Pointer<ffi.Int64> p = Pointer.allocate();
p.store(1337);
Pointer<Int64> p = Pointer.allocate();
p.value = 1337;
int ptr = p.address;
Pointer<ffi.Int64> p2 = Pointer.fromAddress(ptr);
Expect.equals(1337, p2.load<int>());
Pointer<Int64> p2 = Pointer.fromAddress(ptr);
Expect.equals(1337, p2.value);
p.free();
}
void testPointerPointerArithmetic() {
Pointer<ffi.Int64> p = Pointer.allocate(count: 2);
Pointer<ffi.Int64> p2 = p.elementAt(1);
p2.store(100);
Pointer<ffi.Int64> p3 = p.offsetBy(8);
Expect.equals(100, p3.load<int>());
Pointer<Int64> p = Pointer.allocate(count: 2);
Pointer<Int64> p2 = p.elementAt(1);
p2.value = 100;
Pointer<Int64> p3 = p.offsetBy(8);
Expect.equals(100, p3.value);
p.free();
}
void testPointerPointerArithmeticSizes() {
Pointer<ffi.Int64> p = Pointer.allocate(count: 2);
Pointer<ffi.Int64> p2 = p.elementAt(1);
Pointer<Int64> p = Pointer.allocate(count: 2);
Pointer<Int64> p2 = p.elementAt(1);
int addr = p.address;
Expect.equals(addr + 8, p2.address);
p.free();
Pointer<ffi.Int32> p3 = Pointer.allocate(count: 2);
Pointer<ffi.Int32> p4 = p3.elementAt(1);
Pointer<Int32> p3 = Pointer.allocate(count: 2);
Pointer<Int32> p4 = p3.elementAt(1);
addr = p3.address;
Expect.equals(addr + 4, p4.address);
p3.free();
@ -100,9 +99,9 @@ void testPointerAllocateZero() {
//
// Null pointer throws a Dart exception.
bool returnedNullPointer = false;
ffi.Pointer<ffi.Int8> p;
Pointer<Int8> p;
try {
p = Pointer<ffi.Int8>.allocate(count: 0);
p = Pointer<Int8>.allocate(count: 0);
} on Exception {
returnedNullPointer = true;
}
@ -112,289 +111,286 @@ void testPointerAllocateZero() {
}
void testPointerCast() {
Pointer<ffi.Int64> p = Pointer.allocate();
Pointer<ffi.Int32> p2 = p.cast(); // gets the correct type args back
Pointer<Int64> p = Pointer.allocate();
Pointer<Int32> p2 = p.cast(); // gets the correct type args back
p.free();
}
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();
}
Pointer<ffi.Int16> p = Pointer.allocate();
Pointer<ffi.Int64> p2 = generic(p);
Pointer<Int16> p = Pointer.allocate();
Pointer<Int64> p2 = generic(p);
p.free();
}
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();
}
Pointer<ffi.Int16> p = Pointer.allocate();
Pointer<ffi.Int64> p2 = generic(p);
Pointer<Int16> p = Pointer.allocate();
Pointer<Int64> p2 = generic(p);
p.free();
}
void testCastNativeType() {
ffi.Pointer<ffi.Int64> p = Pointer.allocate();
p.cast<ffi.Pointer>();
Pointer<Int64> p = Pointer.allocate();
p.cast<Pointer>();
p.free();
}
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]) {
p.elementAt(i).store(i * 3);
p[i] = i * 3;
}
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();
}
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]) {
p.elementAt(i).store(1.511366173271439e-13);
p[i] = 1.511366173271439e-13;
}
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();
}
void testRangeInt8() {
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
p.store(127);
Expect.equals(127, p.load<int>());
p.store(-128);
Expect.equals(-128, p.load<int>());
Pointer<Int8> p = Pointer.allocate();
p.value = 127;
Expect.equals(127, p.value);
p.value = -128;
Expect.equals(-128, p.value);
Expect.equals(0x0000000000000080, 128);
Expect.equals(0xFFFFFFFFFFFFFF80, -128);
p.store(128);
Expect.equals(-128, p.load<int>()); // truncated and sign extended
p.value = 128;
Expect.equals(-128, p.value); // truncated and sign extended
Expect.equals(0xFFFFFFFFFFFFFF7F, -129);
Expect.equals(0x000000000000007F, 127);
p.store(-129);
Expect.equals(127, p.load<int>()); // truncated
p.value = -129;
Expect.equals(127, p.value); // truncated
p.free();
}
void testRangeUint8() {
ffi.Pointer<ffi.Uint8> p = Pointer.allocate();
p.store(255);
Expect.equals(255, p.load<int>());
p.store(0);
Expect.equals(0, p.load<int>());
Pointer<Uint8> p = Pointer.allocate();
p.value = 255;
Expect.equals(255, p.value);
p.value = 0;
Expect.equals(0, p.value);
Expect.equals(0x0000000000000000, 0);
Expect.equals(0x0000000000000100, 256);
p.store(256);
Expect.equals(0, p.load<int>()); // truncated
p.value = 256;
Expect.equals(0, p.value); // truncated
Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
Expect.equals(0x00000000000000FF, 255);
p.store(-1);
Expect.equals(255, p.load<int>()); // truncated
p.value = -1;
Expect.equals(255, p.value); // truncated
p.free();
}
void testRangeInt16() {
ffi.Pointer<ffi.Int16> p = Pointer.allocate();
p.store(0x7FFF);
Expect.equals(0x7FFF, p.load<int>());
p.store(-0x8000);
Expect.equals(-0x8000, p.load<int>());
p.store(0x8000);
Expect.equals(
0xFFFFFFFFFFFF8000, p.load<int>()); // truncated and sign extended
p.store(-0x8001);
Expect.equals(0x7FFF, p.load<int>()); // truncated
Pointer<Int16> p = Pointer.allocate();
p.value = 0x7FFF;
Expect.equals(0x7FFF, p.value);
p.value = -0x8000;
Expect.equals(-0x8000, p.value);
p.value = 0x8000;
Expect.equals(0xFFFFFFFFFFFF8000, p.value); // truncated and sign extended
p.value = -0x8001;
Expect.equals(0x7FFF, p.value); // truncated
p.free();
}
void testRangeUint16() {
ffi.Pointer<ffi.Uint16> p = Pointer.allocate();
p.store(0xFFFF);
Expect.equals(0xFFFF, p.load<int>());
p.store(0);
Expect.equals(0, p.load<int>());
p.store(0x10000);
Expect.equals(0, p.load<int>()); // truncated
p.store(-1);
Expect.equals(0xFFFF, p.load<int>()); // truncated
Pointer<Uint16> p = Pointer.allocate();
p.value = 0xFFFF;
Expect.equals(0xFFFF, p.value);
p.value = 0;
Expect.equals(0, p.value);
p.value = 0x10000;
Expect.equals(0, p.value); // truncated
p.value = -1;
Expect.equals(0xFFFF, p.value); // truncated
p.free();
}
void testRangeInt32() {
ffi.Pointer<ffi.Int32> p = Pointer.allocate();
p.store(0x7FFFFFFF);
Expect.equals(0x7FFFFFFF, p.load<int>());
p.store(-0x80000000);
Expect.equals(-0x80000000, p.load<int>());
p.store(0x80000000);
Expect.equals(
0xFFFFFFFF80000000, p.load<int>()); // truncated and sign extended
p.store(-0x80000001);
Expect.equals(0x7FFFFFFF, p.load<int>()); // truncated
Pointer<Int32> p = Pointer.allocate();
p.value = 0x7FFFFFFF;
Expect.equals(0x7FFFFFFF, p.value);
p.value = -0x80000000;
Expect.equals(-0x80000000, p.value);
p.value = 0x80000000;
Expect.equals(0xFFFFFFFF80000000, p.value); // truncated and sign extended
p.value = -0x80000001;
Expect.equals(0x7FFFFFFF, p.value); // truncated
p.free();
}
void testRangeUint32() {
ffi.Pointer<ffi.Uint32> p = Pointer.allocate();
p.store(0xFFFFFFFF);
Expect.equals(0xFFFFFFFF, p.load<int>());
p.store(0);
Expect.equals(0, p.load<int>());
p.store(0x100000000);
Expect.equals(0, p.load<int>()); // truncated
p.store(-1);
Expect.equals(0xFFFFFFFF, p.load<int>()); // truncated
Pointer<Uint32> p = Pointer.allocate();
p.value = 0xFFFFFFFF;
Expect.equals(0xFFFFFFFF, p.value);
p.value = 0;
Expect.equals(0, p.value);
p.value = 0x100000000;
Expect.equals(0, p.value); // truncated
p.value = -1;
Expect.equals(0xFFFFFFFF, p.value); // truncated
p.free();
}
void testRangeInt64() {
ffi.Pointer<ffi.Int64> p = Pointer.allocate();
p.store(0x7FFFFFFFFFFFFFFF); // 2 ^ 63 - 1
Expect.equals(0x7FFFFFFFFFFFFFFF, p.load<int>());
p.store(-0x8000000000000000); // -2 ^ 63
Expect.equals(-0x8000000000000000, p.load<int>());
Pointer<Int64> p = Pointer.allocate();
p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
p.value = -0x8000000000000000; // -2 ^ 63
Expect.equals(-0x8000000000000000, p.value);
p.free();
}
void testRangeUint64() {
ffi.Pointer<ffi.Uint64> p = Pointer.allocate();
p.store(0x7FFFFFFFFFFFFFFF); // 2 ^ 63 - 1
Expect.equals(0x7FFFFFFFFFFFFFFF, p.load<int>());
p.store(-0x8000000000000000); // -2 ^ 63 interpreted as 2 ^ 63
Expect.equals(-0x8000000000000000, p.load<int>());
Pointer<Uint64> p = Pointer.allocate();
p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
p.value = -0x8000000000000000; // -2 ^ 63 interpreted as 2 ^ 63
Expect.equals(-0x8000000000000000, p.value);
// Dart allows interpreting bits both signed and unsigned
Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
p.store(-1); // -1 interpreted as 2 ^ 64 - 1
Expect.equals(-1, p.load<int>());
Expect.equals(0xFFFFFFFFFFFFFFFF, p.load<int>());
p.value = -1; // -1 interpreted as 2 ^ 64 - 1
Expect.equals(-1, p.value);
Expect.equals(0xFFFFFFFFFFFFFFFF, p.value);
p.free();
}
void testRangeIntPtr() {
ffi.Pointer<ffi.IntPtr> p = Pointer.allocate();
Pointer<IntPtr> p = Pointer.allocate();
int pAddr = p.address;
p.store(pAddr); // its own address should fit
p.store(0x7FFFFFFF); // and 32 bit addresses should fit
Expect.equals(0x7FFFFFFF, p.load<int>());
p.store(-0x80000000);
Expect.equals(-0x80000000, p.load<int>());
p.value = pAddr; // its own address should fit
p.value = 0x7FFFFFFF; // and 32 bit addresses should fit
Expect.equals(0x7FFFFFFF, p.value);
p.value = -0x80000000;
Expect.equals(-0x80000000, p.value);
p.free();
}
void testFloat() {
ffi.Pointer<ffi.Float> p = Pointer.allocate();
p.store(1.511366173271439e-13);
Expect.equals(1.511366173271439e-13, p.load<double>());
p.store(1.4260258159703532e-105); // float does not have enough precision
Expect.notEquals(1.4260258159703532e-105, p.load<double>());
Pointer<Float> p = Pointer.allocate();
p.value = 1.511366173271439e-13;
Expect.equals(1.511366173271439e-13, p.value);
p.value = 1.4260258159703532e-105; // float does not have enough precision
Expect.notEquals(1.4260258159703532e-105, p.value);
p.free();
}
void testDouble() {
ffi.Pointer<ffi.Double> p = Pointer.allocate();
p.store(1.4260258159703532e-105);
Expect.equals(1.4260258159703532e-105, p.load<double>());
Pointer<Double> p = Pointer.allocate();
p.value = 1.4260258159703532e-105;
Expect.equals(1.4260258159703532e-105, p.value);
p.free();
}
void testVoid() {
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
ffi.Pointer<ffi.Void> p2 = p1.cast(); // make this dart pointer opaque
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<Void> p2 = p1.cast(); // make this dart pointer opaque
p2.address; // we can print the address
p2.free();
}
void testPointerPointer() {
ffi.Pointer<ffi.Int16> p = Pointer.allocate();
p.store(17);
ffi.Pointer<ffi.Pointer<ffi.Int16>> p2 = Pointer.allocate();
p2.store(p);
Expect.equals(17, p2.load<ffi.Pointer<ffi.Int16>>().load<int>());
Pointer<Int16> p = Pointer.allocate();
p.value = 17;
Pointer<Pointer<Int16>> p2 = Pointer.allocate();
p2.value = p;
Expect.equals(17, p2.value.value);
p2.free();
p.free();
}
void testPointerPointerNull() {
Pointer<Pointer<ffi.Int8>> pointerToPointer = Pointer.allocate();
Pointer<ffi.Int8> value = ffi.nullptr.cast();
pointerToPointer.store(value);
value = pointerToPointer.load();
Expect.equals(value, ffi.nullptr);
Pointer<Pointer<Int8>> pointerToPointer = Pointer.allocate();
Pointer<Int8> value = nullptr.cast();
pointerToPointer.value = value;
value = pointerToPointer.value;
Expect.equals(value, nullptr);
value = Pointer.allocate();
pointerToPointer.store(value);
value = pointerToPointer.load();
pointerToPointer.value = value;
value = pointerToPointer.value;
Expect.isNotNull(value);
value.free();
value = ffi.nullptr.cast();
pointerToPointer.store(value);
value = pointerToPointer.load();
Expect.equals(value, ffi.nullptr);
value = nullptr.cast();
pointerToPointer.value = value;
value = pointerToPointer.value;
Expect.equals(value, nullptr);
pointerToPointer.free();
}
void testPointerStoreNull() {
int i = null;
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
Expect.throws(() => p.store(i));
Pointer<Int8> p = Pointer.allocate();
Expect.throws(() => p.value = i);
p.free();
double d = null;
ffi.Pointer<ffi.Float> p2 = Pointer.allocate();
Expect.throws(() => p2.store(d));
Pointer<Float> p2 = Pointer.allocate();
Expect.throws(() => p2.value = d);
p2.free();
Pointer<ffi.Void> x = null;
ffi.Pointer<ffi.Pointer<ffi.Void>> p3 = Pointer.allocate();
Expect.throws(() => p3.store(x));
Pointer<Void> x = null;
Pointer<Pointer<Void>> p3 = Pointer.allocate();
Expect.throws(() => p3.value = x);
p3.free();
}
void testSizeOf() {
Expect.equals(1, ffi.sizeOf<ffi.Int8>());
Expect.equals(2, ffi.sizeOf<ffi.Int16>());
Expect.equals(4, ffi.sizeOf<ffi.Int32>());
Expect.equals(8, ffi.sizeOf<ffi.Int64>());
Expect.equals(1, ffi.sizeOf<ffi.Uint8>());
Expect.equals(2, ffi.sizeOf<ffi.Uint16>());
Expect.equals(4, ffi.sizeOf<ffi.Uint32>());
Expect.equals(8, ffi.sizeOf<ffi.Uint64>());
Expect.equals(
true, 4 == ffi.sizeOf<ffi.IntPtr>() || 8 == ffi.sizeOf<ffi.IntPtr>());
Expect.equals(4, ffi.sizeOf<ffi.Float>());
Expect.equals(8, ffi.sizeOf<ffi.Double>());
Expect.equals(1, sizeOf<Int8>());
Expect.equals(2, sizeOf<Int16>());
Expect.equals(4, sizeOf<Int32>());
Expect.equals(8, sizeOf<Int64>());
Expect.equals(1, sizeOf<Uint8>());
Expect.equals(2, sizeOf<Uint16>());
Expect.equals(4, sizeOf<Uint32>());
Expect.equals(8, sizeOf<Uint64>());
Expect.equals(true, 4 == sizeOf<IntPtr>() || 8 == sizeOf<IntPtr>());
Expect.equals(4, sizeOf<Float>());
Expect.equals(8, sizeOf<Double>());
}
// note: stack overflows at around 15k calls
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) {
head.store(value);
head.value = value;
return;
}
ffi.Pointer<ffi.IntPtr> next = Pointer.allocate();
head.store(next.address);
Pointer<IntPtr> next = Pointer.allocate();
head.value = next.address;
createChain(next, length - 1, value);
}
int getChainValue(ffi.Pointer<ffi.IntPtr> head, int length) {
int getChainValue(Pointer<IntPtr> head, int length) {
if (length == 0) {
return head.load();
return head.value;
}
ffi.Pointer<ffi.IntPtr> next = Pointer.fromAddress(head.load());
Pointer<IntPtr> next = Pointer.fromAddress(head.value);
return getChainValue(next, length - 1);
}
void freeChain(ffi.Pointer<ffi.IntPtr> head, int length) {
ffi.Pointer<ffi.IntPtr> next = Pointer.fromAddress(head.load());
void freeChain(Pointer<IntPtr> head, int length) {
Pointer<IntPtr> next = Pointer.fromAddress(head.value);
head.free();
if (length == 0) {
return;
@ -402,7 +398,7 @@ void testPointerChain(int length) {
freeChain(next, length - 1);
}
ffi.Pointer<ffi.IntPtr> head = Pointer.allocate();
Pointer<IntPtr> head = Pointer.allocate();
createChain(head, length, 512);
int tailValue = getChainValue(head, length);
Expect.equals(512, tailValue);
@ -410,56 +406,56 @@ void testPointerChain(int length) {
}
void testTypeTest() {
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
Expect.isTrue(p is ffi.Pointer);
Pointer<Int8> p = Pointer.allocate();
Expect.isTrue(p is Pointer);
p.free();
}
void testToString() {
ffi.Pointer<ffi.Int16> p = Pointer.allocate();
Pointer<Int16> p = Pointer.allocate();
Expect.stringEquals(
"Pointer<Int16>: address=0x", p.toString().substring(0, 26));
p.free();
ffi.Pointer<ffi.Int64> p2 = Pointer.fromAddress(0x123abc);
Pointer<Int64> p2 = Pointer.fromAddress(0x123abc);
Expect.stringEquals("Pointer<Int64>: address=0x123abc", p2.toString());
}
void testEquality() {
ffi.Pointer<ffi.Int8> p = Pointer.fromAddress(12345678);
ffi.Pointer<ffi.Int8> p2 = Pointer.fromAddress(12345678);
Pointer<Int8> p = Pointer.fromAddress(12345678);
Pointer<Int8> p2 = Pointer.fromAddress(12345678);
Expect.equals(p, p2);
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.hashCode, p3.hashCode);
Expect.notEquals(p, null);
Expect.notEquals(null, p);
ffi.Pointer<ffi.Int8> p4 = p.offsetBy(1337);
Pointer<Int8> p4 = p.offsetBy(1337);
Expect.notEquals(p, p4);
}
typedef Int8UnOp = ffi.Int8 Function(ffi.Int8);
typedef Int8UnOp = Int8 Function(Int8);
void testAllocateGeneric() {
ffi.Pointer<T> generic<T extends ffi.NativeType>() {
ffi.Pointer<T> pointer;
Pointer<T> generic<T extends NativeType>() {
Pointer<T> pointer;
pointer = Pointer.allocate();
return pointer;
}
ffi.Pointer p = generic<ffi.Int64>();
Pointer p = generic<Int64>();
p.free();
}
void testAllocateVoid() {
Expect.throws(() {
ffi.Pointer<ffi.Void> p = Pointer.allocate();
Pointer<Void> p = Pointer.allocate();
});
}
void testAllocateNativeFunction() {
Expect.throws(() {
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.allocate();
Pointer<NativeFunction<Int8UnOp>> p = Pointer.allocate();
});
}
@ -470,42 +466,42 @@ void testAllocateNativeType() {
}
void testSizeOfGeneric() {
int generic<T extends ffi.Pointer>() {
int generic<T extends Pointer>() {
int size;
size = ffi.sizeOf<T>();
size = sizeOf<T>();
return size;
}
int size = generic<ffi.Pointer<ffi.Int64>>();
int size = generic<Pointer<Int64>>();
Expect.isTrue(size == 8 || size == 4);
}
void testSizeOfVoid() {
Expect.throws(() {
ffi.sizeOf<ffi.Void>();
sizeOf<Void>();
});
}
void testSizeOfNativeFunction() {
Expect.throws(() {
ffi.sizeOf<ffi.NativeFunction<Int8UnOp>>();
sizeOf<NativeFunction<Int8UnOp>>();
});
}
void testSizeOfNativeType() {
Expect.throws(() {
ffi.sizeOf();
sizeOf();
});
}
void testDynamicInvocation() {
dynamic p = Pointer<ffi.Int8>.allocate();
dynamic p = Pointer<Int8>.allocate();
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.
final int addr = p.address;
final Pointer<ffi.Int16> p2 = p.cast<ffi.Int16>();
final Pointer<Int16> p2 = p.cast<Int16>();
p.free();
}

View File

@ -42,7 +42,7 @@ main() {
void testInt8Load() {
// Load
Pointer<Int8> ptr = Pointer.allocate();
ptr.store(0xff);
ptr.value = 0xff;
Int8List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
@ -55,14 +55,14 @@ void testInt8Store() {
Int8List list = ptr.asExternalTypedData();
list[0] = 0xff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
Expect.equals(ptr.value, -1);
ptr.free();
}
void testUint8Load() {
// Load
Pointer<Uint8> ptr = Pointer.allocate();
ptr.store(0xff);
ptr.value = 0xff;
Uint8List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xff);
Expect.equals(list.length, 1);
@ -75,14 +75,14 @@ void testUint8Store() {
Uint8List list = ptr.asExternalTypedData();
list[0] = 0xff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xff);
Expect.equals(ptr.value, 0xff);
ptr.free();
}
void testInt16Load() {
// Load
Pointer<Int16> ptr = Pointer.allocate();
ptr.store(0xffff);
ptr.value = 0xffff;
Int16List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
@ -95,14 +95,14 @@ void testInt16Store() {
Int16List list = ptr.asExternalTypedData();
list[0] = 0xffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
Expect.equals(ptr.value, -1);
ptr.free();
}
void testUint16Load() {
// Load
Pointer<Uint16> ptr = Pointer.allocate();
ptr.store(0xffff);
ptr.value = 0xffff;
Uint16List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffff);
Expect.equals(list.length, 1);
@ -115,14 +115,14 @@ void testUint16Store() {
Uint16List list = ptr.asExternalTypedData();
list[0] = 0xffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xffff);
Expect.equals(ptr.value, 0xffff);
ptr.free();
}
void testInt32Load() {
// Load
Pointer<Int32> ptr = Pointer.allocate();
ptr.store(0xffffffff);
ptr.value = 0xffffffff;
Int32List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
@ -135,14 +135,14 @@ void testInt32Store() {
Int32List list = ptr.asExternalTypedData();
list[0] = 0xffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
Expect.equals(ptr.value, -1);
ptr.free();
}
void testUint32Load() {
// Load
Pointer<Uint32> ptr = Pointer.allocate();
ptr.store(0xffffffff);
ptr.value = 0xffffffff;
Uint32List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffffffff);
Expect.equals(list.length, 1);
@ -155,14 +155,14 @@ void testUint32Store() {
Uint32List list = ptr.asExternalTypedData();
list[0] = 0xffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xffffffff);
Expect.equals(ptr.value, 0xffffffff);
ptr.free();
}
void testInt64Load() {
// Load
Pointer<Int64> ptr = Pointer.allocate();
ptr.store(0xffffffffffffffff);
ptr.value = 0xffffffffffffffff;
Int64List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
@ -175,14 +175,14 @@ void testInt64Store() {
Int64List list = ptr.asExternalTypedData();
list[0] = 0xffffffffffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
Expect.equals(ptr.value, -1);
ptr.free();
}
void testUint64Load() {
// Load
Pointer<Uint64> ptr = Pointer.allocate();
ptr.store(0xffffffffffffffff);
ptr.value = 0xffffffffffffffff;
Uint64List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffffffffffffffff);
Expect.equals(list.length, 1);
@ -195,7 +195,7 @@ void testUint64Store() {
Uint64List list = ptr.asExternalTypedData();
list[0] = 0xffffffffffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xffffffffffffffff);
Expect.equals(ptr.value, 0xffffffffffffffff);
ptr.free();
}
@ -217,7 +217,7 @@ double maxDouble = (2 - pow(2, -52)) * pow(2, pow(2, 10) - 1);
void testFloatLoad() {
// Load
Pointer<Float> ptr = Pointer.allocate();
ptr.store(maxFloat);
ptr.value = maxFloat;
Float32List list = ptr.asExternalTypedData();
Expect.equals(list[0], maxFloat);
Expect.equals(list.length, 1);
@ -230,14 +230,14 @@ void testFloatStore() {
Float32List list = ptr.asExternalTypedData();
list[0] = maxFloat;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<double>(), maxFloat);
Expect.equals(ptr.value, maxFloat);
ptr.free();
}
void testDoubleLoad() {
// Load
Pointer<Double> ptr = Pointer.allocate();
ptr.store(maxDouble);
ptr.value = maxDouble;
Float64List list = ptr.asExternalTypedData();
Expect.equals(list[0], maxDouble);
Expect.equals(list.length, 1);
@ -250,7 +250,7 @@ void testDoubleStore() {
Float64List list = ptr.asExternalTypedData();
list[0] = maxDouble;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<double>(), maxDouble);
Expect.equals(ptr.value, maxDouble);
ptr.free();
}
@ -258,7 +258,7 @@ void testArrayLoad() {
const int count = 0x100;
Pointer<Int32> ptr = Pointer.allocate(count: count);
for (int i = 0; i < count; ++i) {
ptr.elementAt(i).store(i);
ptr[i] = i;
}
Int32List array = ptr.asExternalTypedData(count: count);
for (int i = 0; i < count; ++i) {
@ -275,7 +275,7 @@ void testArrayStore() {
array[i] = i;
}
for (int i = 0; i < count; ++i) {
Expect.equals(ptr.elementAt(i).load<int>(), i);
Expect.equals(ptr[i], i);
}
ptr.free();
}

View File

@ -143,7 +143,7 @@ double manyArgs(
}
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>);
Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr.elementAt(1);
@ -182,15 +182,19 @@ void testGC() {
typedef WaitForHelper = Void Function(Pointer<Void>);
void waitForHelper(Pointer<Void> helper) {
print("helper: $helper");
testLibrary.lookupFunction<WaitForHelper, WaitForHelper>("WaitForHelper")(helper);
testLibrary
.lookupFunction<WaitForHelper, WaitForHelper>("WaitForHelper")(helper);
}
final List<Test> testcases = [
Test("SimpleAddition", Pointer.fromFunction<SimpleAdditionType>(simpleAddition, 0)),
Test("IntComputation", Pointer.fromFunction<IntComputationType>(intComputation, 0)),
Test(
"UintComputation", Pointer.fromFunction<UintComputationType>(uintComputation, 0)),
Test("SimpleMultiply", Pointer.fromFunction<SimpleMultiplyType>(simpleMultiply, 0.0)),
Test("SimpleAddition",
Pointer.fromFunction<SimpleAdditionType>(simpleAddition, 0)),
Test("IntComputation",
Pointer.fromFunction<IntComputationType>(intComputation, 0)),
Test("UintComputation",
Pointer.fromFunction<UintComputationType>(uintComputation, 0)),
Test("SimpleMultiply",
Pointer.fromFunction<SimpleMultiplyType>(simpleMultiply, 0.0)),
Test("SimpleMultiplyFloat",
Pointer.fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat, 0.0)),
Test("ManyInts", Pointer.fromFunction<ManyIntsType>(manyInts, 0)),
@ -202,17 +206,17 @@ final List<Test> testcases = [
Test("ReturnVoid", Pointer.fromFunction<ReturnVoid>(returnVoid)),
Test("ThrowExceptionDouble",
Pointer.fromFunction<ThrowExceptionDouble>(throwExceptionDouble, 42.0)),
Test(
"ThrowExceptionPointer",
Pointer.fromFunction<ThrowExceptionPointer>(
throwExceptionPointer)),
Test("ThrowException", Pointer.fromFunction<ThrowExceptionInt>(throwExceptionInt, 42)),
Test("ThrowExceptionPointer",
Pointer.fromFunction<ThrowExceptionPointer>(throwExceptionPointer)),
Test("ThrowException",
Pointer.fromFunction<ThrowExceptionInt>(throwExceptionInt, 42)),
Test("GC", Pointer.fromFunction<ReturnVoid>(testGC)),
Test("UnprotectCode", Pointer.fromFunction<WaitForHelper>(waitForHelper)),
];
testCallbackWrongThread() =>
Test("CallbackWrongThread", Pointer.fromFunction<ReturnVoid>(returnVoid)).run();
Test("CallbackWrongThread", Pointer.fromFunction<ReturnVoid>(returnVoid))
.run();
testCallbackOutsideIsolate() =>
Test("CallbackOutsideIsolate", Pointer.fromFunction<ReturnVoid>(returnVoid))
@ -227,7 +231,8 @@ isolateHelper(int callbackPointer) {
}
testCallbackWrongIsolate() async {
final int callbackPointer = Pointer.fromFunction<ReturnVoid>(returnVoid).address;
final int callbackPointer =
Pointer.fromFunction<ReturnVoid>(returnVoid).address;
final ReceivePort exitPort = ReceivePort();
await Isolate.spawn(isolateHelper, callbackPointer,
errorsAreFatal: true, onExit: exitPort.sendPort);
@ -262,7 +267,7 @@ void main() async {
await testCallbackWrongIsolate(); //# 03: ok
}
testManyCallbacks(); //# 04: ok
testManyCallbacks(); //# 04: ok
}
void testManyCallbacks() {

View File

@ -9,8 +9,7 @@
library FfiTest;
import 'dart:ffi' as ffi;
import 'dart:ffi' show Pointer;
import 'dart:ffi';
import 'dylib_utils.dart';
@ -27,24 +26,23 @@ void main() {
testFunctionWithVeryLargeStruct();
}
ffi.DynamicLibrary ffiTestFunctions =
dlopenPlatformSpecific("ffi_test_functions");
DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
/// pass a struct to a c function and get a struct as return value
void testFunctionWithStruct() {
ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
Pointer<NativeFunction<NativeCoordinateOp>> p1 =
ffiTestFunctions.lookup("TransposeCoordinate");
NativeCoordinateOp f1 = p1.asFunction();
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;
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(30.0, c1.load<Coordinate>().y);
Expect.approxEquals(20.0, c1.ref.x);
Expect.approxEquals(30.0, c1.ref.y);
Expect.approxEquals(42.0, result.x);
Expect.approxEquals(84.0, result.y);
@ -55,13 +53,13 @@ void testFunctionWithStruct() {
/// pass an array of structs to a c funtion
void testFunctionWithStructArray() {
ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
Pointer<NativeFunction<NativeCoordinateOp>> p1 =
ffiTestFunctions.lookup("CoordinateElemAt1");
NativeCoordinateOp f1 = p1.asFunction();
Coordinate c1 = Pointer<Coordinate>.allocate(count: 3).load();
Coordinate c2 = c1.addressOf.elementAt(1).load();
Coordinate c3 = c1.addressOf.elementAt(2).load();
Coordinate c1 = Pointer<Coordinate>.allocate(count: 3).ref;
Coordinate c2 = c1.addressOf[1];
Coordinate c3 = c1.addressOf[2];
c1.x = 10.0;
c1.y = 10.0;
c1.next = c3.addressOf;
@ -72,7 +70,7 @@ void testFunctionWithStructArray() {
c3.y = 30.0;
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.y);
@ -80,15 +78,15 @@ void testFunctionWithStructArray() {
}
typedef VeryLargeStructSum = int Function(Pointer<VeryLargeStruct>);
typedef NativeVeryLargeStructSum = ffi.Int64 Function(Pointer<VeryLargeStruct>);
typedef NativeVeryLargeStructSum = Int64 Function(Pointer<VeryLargeStruct>);
void testFunctionWithVeryLargeStruct() {
ffi.Pointer<ffi.NativeFunction<NativeVeryLargeStructSum>> p1 =
Pointer<NativeFunction<NativeVeryLargeStructSum>> p1 =
ffiTestFunctions.lookup("SumVeryLargeStruct");
VeryLargeStructSum f = p1.asFunction();
VeryLargeStruct vls1 = Pointer<VeryLargeStruct>.allocate(count: 2).load();
VeryLargeStruct vls2 = vls1.addressOf.elementAt(1).load();
VeryLargeStruct vls1 = Pointer<VeryLargeStruct>.allocate(count: 2).ref;
VeryLargeStruct vls2 = vls1.addressOf[1];
List<VeryLargeStruct> structs = [vls1, vls2];
for (VeryLargeStruct struct in structs) {
struct.a = 1;
@ -108,9 +106,9 @@ void testFunctionWithVeryLargeStruct() {
vls1.numChildren = 2;
vls1.children = vls1.addressOf;
vls2.parent = vls2.addressOf;
vls2.parent = ffi.nullptr.cast();
vls2.parent = nullptr.cast();
vls2.numChildren = 0;
vls2.children = ffi.nullptr.cast();
vls2.children = nullptr.cast();
int result = f(vls1.addressOf);
Expect.equals(2051, result);

View File

@ -15,8 +15,7 @@
library FfiTest;
import 'dart:ffi' as ffi;
import 'dart:ffi' show Pointer;
import 'dart:ffi';
import 'dylib_utils.dart';
@ -47,27 +46,24 @@ void main() {
}
}
ffi.DynamicLibrary ffiTestFunctions =
dlopenPlatformSpecific("ffi_test_functions");
DynamicLibrary ffiTestFunctions = 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 BinaryOp = int Function(int, int);
typedef GenericBinaryOp<T> = int Function(int, T);
void testNativeFunctionFromCast() {
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
ffi.Pointer<ffi.NativeFunction<NativeBinaryOp>> p2 = p1.cast();
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<NativeFunction<NativeBinaryOp>> p2 = p1.cast();
p2.asFunction<BinaryOp>();
p2.asFunction<GenericBinaryOp<int>>();
p1.free();
}
typedef NativeQuadOpSigned = ffi.Int64 Function(
ffi.Int8, ffi.Int16, ffi.Int32, ffi.Int64);
typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
typedef QuadOp = int Function(int, int, int, int);
typedef NativeQuadOpUnsigned = ffi.Uint64 Function(
ffi.Uint8, ffi.Uint16, ffi.Uint32, ffi.Uint64);
typedef NativeQuadOpUnsigned = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
BinaryOp sumPlus42 =
ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
@ -86,76 +82,76 @@ void testNativeFunctionFromLookup() {
-0x8000000000000000, intComputation(0, 0, 0, -0x8000000000000000));
}
typedef NativeReturnMaxUint8 = ffi.Uint8 Function();
typedef NativeReturnMaxUint8 = Uint8 Function();
int Function() returnMaxUint8 = ffiTestFunctions
.lookup("ReturnMaxUint8")
.cast<ffi.NativeFunction<NativeReturnMaxUint8>>()
.cast<NativeFunction<NativeReturnMaxUint8>>()
.asFunction();
typedef NativeReturnMaxUint16 = ffi.Uint16 Function();
typedef NativeReturnMaxUint16 = Uint16 Function();
int Function() returnMaxUint16 = ffiTestFunctions
.lookup("ReturnMaxUint16")
.cast<ffi.NativeFunction<NativeReturnMaxUint16>>()
.cast<NativeFunction<NativeReturnMaxUint16>>()
.asFunction();
typedef NativeReturnMaxUint32 = ffi.Uint32 Function();
typedef NativeReturnMaxUint32 = Uint32 Function();
int Function() returnMaxUint32 = ffiTestFunctions
.lookup("ReturnMaxUint32")
.cast<ffi.NativeFunction<NativeReturnMaxUint32>>()
.cast<NativeFunction<NativeReturnMaxUint32>>()
.asFunction();
typedef NativeReturnMinInt8 = ffi.Int8 Function();
typedef NativeReturnMinInt8 = Int8 Function();
int Function() returnMinInt8 = ffiTestFunctions
.lookup("ReturnMinInt8")
.cast<ffi.NativeFunction<NativeReturnMinInt8>>()
.cast<NativeFunction<NativeReturnMinInt8>>()
.asFunction();
typedef NativeReturnMinInt16 = ffi.Int16 Function();
typedef NativeReturnMinInt16 = Int16 Function();
int Function() returnMinInt16 = ffiTestFunctions
.lookup("ReturnMinInt16")
.cast<ffi.NativeFunction<NativeReturnMinInt16>>()
.cast<NativeFunction<NativeReturnMinInt16>>()
.asFunction();
typedef NativeReturnMinInt32 = ffi.Int32 Function();
typedef NativeReturnMinInt32 = Int32 Function();
int Function() returnMinInt32 = ffiTestFunctions
.lookup("ReturnMinInt32")
.cast<ffi.NativeFunction<NativeReturnMinInt32>>()
.cast<NativeFunction<NativeReturnMinInt32>>()
.asFunction();
typedef NativeTakeMaxUint8 = ffi.IntPtr Function(ffi.Uint8);
typedef NativeTakeMaxUint8 = IntPtr Function(Uint8);
int Function(int) takeMaxUint8 = ffiTestFunctions
.lookup("TakeMaxUint8")
.cast<ffi.NativeFunction<NativeTakeMaxUint8>>()
.cast<NativeFunction<NativeTakeMaxUint8>>()
.asFunction();
typedef NativeTakeMaxUint16 = ffi.IntPtr Function(ffi.Uint16);
typedef NativeTakeMaxUint16 = IntPtr Function(Uint16);
int Function(int) takeMaxUint16 = ffiTestFunctions
.lookup("TakeMaxUint16")
.cast<ffi.NativeFunction<NativeTakeMaxUint16>>()
.cast<NativeFunction<NativeTakeMaxUint16>>()
.asFunction();
typedef NativeTakeMaxUint32 = ffi.IntPtr Function(ffi.Uint32);
typedef NativeTakeMaxUint32 = IntPtr Function(Uint32);
int Function(int) takeMaxUint32 = ffiTestFunctions
.lookup("TakeMaxUint32")
.cast<ffi.NativeFunction<NativeTakeMaxUint32>>()
.cast<NativeFunction<NativeTakeMaxUint32>>()
.asFunction();
typedef NativeTakeMinInt8 = ffi.IntPtr Function(ffi.Int8);
typedef NativeTakeMinInt8 = IntPtr Function(Int8);
int Function(int) takeMinInt8 = ffiTestFunctions
.lookup("TakeMinInt8")
.cast<ffi.NativeFunction<NativeTakeMinInt8>>()
.cast<NativeFunction<NativeTakeMinInt8>>()
.asFunction();
typedef NativeTakeMinInt16 = ffi.IntPtr Function(ffi.Int16);
typedef NativeTakeMinInt16 = IntPtr Function(Int16);
int Function(int) takeMinInt16 = ffiTestFunctions
.lookup("TakeMinInt16")
.cast<ffi.NativeFunction<NativeTakeMinInt16>>()
.cast<NativeFunction<NativeTakeMinInt16>>()
.asFunction();
typedef NativeTakeMinInt32 = ffi.IntPtr Function(ffi.Int32);
typedef NativeTakeMinInt32 = IntPtr Function(Int32);
int Function(int) takeMinInt32 = ffiTestFunctions
.lookup("TakeMinInt32")
.cast<ffi.NativeFunction<NativeTakeMinInt32>>()
.cast<NativeFunction<NativeTakeMinInt32>>()
.asFunction();
void testExtension() {
@ -188,8 +184,8 @@ void test64bitInterpretations() {
Expect.equals(-1, uintComputation(0, 0, 0, -1));
}
typedef NativeSenaryOp = ffi.Int64 Function(
ffi.Int8, ffi.Int16, ffi.Int32, ffi.Uint8, ffi.Uint16, ffi.Uint32);
typedef NativeSenaryOp = Int64 Function(
Int8, Int16, Int32, Uint8, Uint16, Uint32);
typedef SenaryOp = int Function(int, int, int, int, int, int);
SenaryOp sumSmallNumbers = ffiTestFunctions
@ -213,7 +209,7 @@ void testTruncation() {
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);
DoubleUnaryOp times1_337Double = ffiTestFunctions
@ -223,7 +219,7 @@ void testNativeFunctionDoubles() {
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
.lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
@ -232,17 +228,8 @@ void testNativeFunctionFloats() {
Expect.approxEquals(1337.0, times1_337Float(1000.0));
}
typedef NativeDecenaryOp = ffi.IntPtr Function(
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr);
typedef NativeDecenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
typedef DecenaryOp = int Function(
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));
}
typedef NativeUndenaryOp = ffi.IntPtr Function(
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr,
ffi.IntPtr);
typedef NativeUndenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
typedef UndenaryOp = int Function(
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));
}
typedef NativeDoubleDecenaryOp = ffi.Double Function(
ffi.Double,
ffi.Double,
ffi.Double,
ffi.Double,
ffi.Double,
ffi.Double,
ffi.Double,
ffi.Double,
ffi.Double,
ffi.Double);
typedef NativeDoubleDecenaryOp = Double Function(Double, Double, Double, Double,
Double, Double, Double, Double, Double, Double);
typedef DoubleDecenaryOp = double Function(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));
}
typedef NativeVigesimalOp = ffi.Double Function(
ffi.IntPtr,
ffi.Float,
ffi.IntPtr,
ffi.Double,
ffi.IntPtr,
ffi.Float,
ffi.IntPtr,
ffi.Double,
ffi.IntPtr,
ffi.Float,
ffi.IntPtr,
ffi.Double,
ffi.IntPtr,
ffi.Float,
ffi.IntPtr,
ffi.Double,
ffi.IntPtr,
ffi.Float,
ffi.IntPtr,
ffi.Double);
typedef NativeVigesimalOp = Double Function(
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double);
typedef VigesimalOp = double Function(
int,
double,
@ -350,19 +318,18 @@ void testNativeFunctionManyArguments3() {
14.0, 15, 16.0, 17, 18.0, 19, 20.0));
}
typedef Int64PointerUnOp = ffi.Pointer<ffi.Int64> Function(
ffi.Pointer<ffi.Int64>);
typedef Int64PointerUnOp = Pointer<Int64> Function(Pointer<Int64>);
Int64PointerUnOp assign1337Index1 = ffiTestFunctions
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
void testNativeFunctionPointer() {
ffi.Pointer<ffi.Int64> p2 = Pointer.allocate(count: 2);
p2.store(42);
p2.elementAt(1).store(1000);
ffi.Pointer<ffi.Int64> result = assign1337Index1(p2);
Expect.equals(1337, result.load<int>());
Expect.equals(1337, p2.elementAt(1).load<int>());
Pointer<Int64> p2 = Pointer.allocate(count: 2);
p2.value = 42;
p2[1] = 1000;
Pointer<Int64> result = assign1337Index1(p2);
Expect.equals(1337, result.value);
Expect.equals(1337, p2[1]);
Expect.equals(p2.elementAt(1).address, result.address);
p2.free();
}
@ -387,24 +354,24 @@ Int64PointerUnOp nullableInt64ElemAt1 = ffiTestFunctions
.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("NullableInt64ElemAt1");
void testNullPointers() {
Pointer<ffi.Int64> result = nullableInt64ElemAt1(ffi.nullptr.cast());
Expect.equals(result, ffi.nullptr);
Pointer<Int64> result = nullableInt64ElemAt1(nullptr.cast());
Expect.equals(result, nullptr);
Pointer<ffi.Int64> p2 = Pointer.allocate(count: 2);
Pointer<Int64> p2 = Pointer.allocate(count: 2);
result = nullableInt64ElemAt1(p2);
Expect.notEquals(result, ffi.nullptr);
Expect.notEquals(result, nullptr);
p2.free();
}
typedef NativeFloatPointerToBool = ffi.Uint8 Function(ffi.Pointer<ffi.Float>);
typedef FloatPointerToBool = int Function(ffi.Pointer<ffi.Float>);
typedef NativeFloatPointerToBool = Uint8 Function(Pointer<Float>);
typedef FloatPointerToBool = int Function(Pointer<Float>);
FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
void testFloatRounding() {
Pointer<ffi.Float> p2 = Pointer.allocate();
p2.store(1337.0);
Pointer<Float> p2 = Pointer.allocate();
p2.value = 1337.0;
int result = isRoughly1337(p2);
Expect.equals(1, result);
@ -412,7 +379,7 @@ void testFloatRounding() {
p2.free();
}
typedef NativeFloatToVoid = ffi.Void Function(ffi.Float);
typedef NativeFloatToVoid = Void Function(Float);
typedef DoubleToVoid = void Function(double);
DoubleToVoid devNullFloat = ffiTestFunctions
@ -426,7 +393,7 @@ void testVoidReturn() {
Expect.isNull(result);
}
typedef NativeVoidToFloat = ffi.Float Function();
typedef NativeVoidToFloat = Float Function();
typedef VoidToDouble = double Function();
VoidToDouble inventFloatValue = ffiTestFunctions

View File

@ -15,8 +15,8 @@
// Note #2: When we switch to extension methods we will _only_ use the static
// type of the container.
//
// ===== a.store(b) ======
// Does a.store(b), where a and b have specific static and dynamic types: run
// ===== a.value = b ======
// Does a.value = b, where a and b have specific static and dynamic types: run
// fine, fail at compile time, or fail at runtime?
// =======================
// 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
//
// ====== final c = a.load() ======
// What is the (inferred) static type and runtime type of `a.load()`. Note that
// ====== final c = a.value ======
// 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(); }
// ================================
// a a.load()
// a a.value
// inferred static type*//runtime type
// P<P<I>>//P<P<I>> P<I>//P<I>
//
@ -43,8 +43,8 @@
//
// * The inferred static type when we get extension methods.
//
// ====== b = a.load() ======
// What happens when we try to assign the result of a.load() to variable b with
// ====== b = a.value ======
// 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.
// ==========================
// b P<I> P<NT>
@ -64,13 +64,13 @@ import 'dart:ffi';
import "package:expect/expect.dart";
// ===== a.store(b) ======
// ===== a.value = b ======
// The tests follow table cells left to right, top to bottom.
void store1() {
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
final Pointer<Int8> b = Pointer<Int8>.allocate();
a.store(b);
a.value = b;
a.free();
b.free();
@ -81,8 +81,9 @@ void store2() {
final Pointer<NativeType> b =
Pointer<Int8>.allocate(); // Reified Pointer<Int8> at runtime.
// We disable implicit downcasts, they will go away when NNBD lands.
a.store(b); //# 1: compile-time error
// Successful implicit downcast of argument at runtime.
// Should succeed now, should statically be rejected when NNBD lands.
a.value = b;
a.free();
b.free();
@ -93,8 +94,11 @@ void store3() {
final Pointer<NativeType> b =
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
// We disable implicit downcasts, they will go away when NNBD lands.
a.store(b); //# 2: compile-time error
// Failing implicit downcast of argument at runtime.
// Should fail now at runtime, should statically be rejected when NNBD lands.
Expect.throws(() {
a.value = b;
});
a.free();
b.free();
@ -106,7 +110,7 @@ void store4() {
final Pointer<Int8> b = Pointer<Int8>.allocate();
a.store(b);
a.value = b;
a.free();
b.free();
@ -119,7 +123,7 @@ void store5() {
final Pointer<NativeType> b =
Pointer<Int8>.allocate(); // Reified as Pointer<Int8> at runtime.
a.store(b);
a.value = b;
a.free();
b.free();
@ -133,7 +137,7 @@ void store6() {
// Fails on type check of argument.
Expect.throws(() {
a.store(b);
a.value = b;
});
a.free();
@ -145,7 +149,7 @@ void store7() {
Pointer<Pointer<NativeType>>.allocate();
final Pointer<Int8> b = Pointer<Int8>.allocate();
a.store(b);
a.value = b;
a.free();
b.free();
@ -158,7 +162,7 @@ void store8() {
// Reified as Pointer<Int8> at runtime.
final Pointer<NativeType> b = Pointer<Int8>.allocate();
a.store(b);
a.value = b;
a.free();
b.free();
@ -170,18 +174,18 @@ void store9() {
final Pointer<NativeType> b =
Pointer<Int8>.allocate().cast<Pointer<NativeType>>();
a.store(b);
a.value = b;
a.free();
b.free();
}
// ====== b = a.load() ======
// ====== b = a.value ======
// The tests follow table cells left to right, top to bottom.
void load1() {
final Pointer<Pointer<Int8>> a = Pointer<Pointer<Int8>>.allocate();
Pointer<Int8> b = a.load();
Pointer<Int8> b = a.value;
Expect.type<Pointer<Int8>>(b);
a.free();
@ -190,7 +194,7 @@ void load1() {
void load2() {
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);
a.free();
@ -200,7 +204,7 @@ void load3() {
// Reified as Pointer<Pointer<Int8>> at runtime.
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);
a.free();
@ -211,7 +215,7 @@ void load4() {
final Pointer<Pointer<NativeType>> a = Pointer<Pointer<Int8>>.allocate();
// Return value runtime type is Pointer<Int8>.
Pointer<NativeType> b = a.load();
Pointer<NativeType> b = a.value;
Expect.type<Pointer<Int8>>(b);
a.free();
@ -224,7 +228,7 @@ void load5() {
// Failing implicit downcast of return value at runtime.
// Should fail now at runtime, should statically be rejected when NNBD lands.
Expect.throws(() {
Pointer<Int8> b = a.load<Pointer<NativeType>>();
Pointer<Int8> b = a.value;
});
a.free();
@ -234,7 +238,7 @@ void load6() {
final Pointer<Pointer<NativeType>> a =
Pointer<Pointer<NativeType>>.allocate();
Pointer<NativeType> b = a.load();
Pointer<NativeType> b = a.value;
Expect.type<Pointer<NativeType>>(b);
a.free();

View File

@ -8,8 +8,7 @@
library FfiTest;
import 'dart:ffi' as ffi;
import 'dart:ffi' show Pointer;
import 'dart:ffi';
import 'dylib_utils.dart';
@ -47,29 +46,29 @@ void main() {
testNativeFunctionSignatureInvalidOptionalPositional();
}
typedef Int8UnOp = ffi.Int8 Function(ffi.Int8);
typedef Int8UnOp = Int8 Function(Int8);
typedef IntUnOp = int Function(int);
void testGetGeneric() {
int generic(ffi.Pointer p) {
int generic(Pointer p) {
int result;
result = p.load<int>(); //# 20: compile-time error
result = p.value; //# 20: compile-time error
return result;
}
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
p.store(123);
ffi.Pointer loseType = p;
Pointer<Int8> p = Pointer.allocate();
p.value = 123;
Pointer loseType = p;
generic(loseType);
p.free();
}
void testGetGeneric2() {
T generic<T extends Object>() {
Pointer<ffi.Int8> p = Pointer.allocate();
p.store(123);
Pointer<Int8> p = Pointer.allocate();
p.value = 123;
T result;
result = p.load<T>(); //# 21: compile-time error
result = p.value; //# 21: compile-time error
p.free();
return result;
}
@ -78,50 +77,50 @@ void testGetGeneric2() {
}
void testGetVoid() {
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
ffi.Pointer<ffi.Void> p2 = p1.cast();
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<Void> p2 = p1.cast();
p2.load<int>(); //# 22: compile-time error
p2.value; //# 22: compile-time error
p1.free();
}
void testGetNativeFunction() {
Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
IntUnOp f = p.load(); //# 23: compile-time error
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
IntUnOp f = p.value; //# 23: compile-time error
}
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() {
ffi.Pointer<ffi.Pointer<ffi.Int16>> p = Pointer.allocate();
ffi.Pointer<ffi.Int16> typedNull = ffi.nullptr.cast();
p.store(typedNull);
Pointer<Pointer<Int16>> p = Pointer.allocate();
Pointer<Int16> typedNull = nullptr.cast();
p.value = typedNull;
// 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();
}
void testSetGeneric() {
void generic(ffi.Pointer p) {
p.store(123); //# 26: compile-time error
void generic(Pointer p) {
p.value = 123; //# 26: compile-time error
}
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
p.store(123);
ffi.Pointer loseType = p;
Pointer<Int8> p = Pointer.allocate();
p.value = 123;
Pointer loseType = p;
generic(loseType);
p.free();
}
void testSetGeneric2() {
void generic<T extends Object>(T arg) {
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
p.store(arg); //# 27: compile-time error
Pointer<Int8> p = Pointer.allocate();
p.value = arg; //# 27: compile-time error
p.free();
}
@ -129,33 +128,33 @@ void testSetGeneric2() {
}
void testSetVoid() {
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
ffi.Pointer<ffi.Void> p2 = p1.cast();
Pointer<IntPtr> p1 = Pointer.allocate();
Pointer<Void> p2 = p1.cast();
p2.store(1234); //# 28: compile-time error
p2.value = 1234; //# 28: compile-time error
p1.free();
}
void testSetNativeFunction() {
Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
IntUnOp f = (a) => a + 1;
p.store(f); //# 29: compile-time error
p.value = f; //# 29: compile-time error
}
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() {
// the pointer to pointer types must match up
ffi.Pointer<ffi.Int8> pHelper = Pointer.allocate();
pHelper.store(123);
Pointer<Int8> pHelper = Pointer.allocate();
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
p.store(pHelper); //# 40: compile-time error
p.value = pHelper; //# 40: compile-time error
pHelper.free();
p.free();
@ -163,7 +162,7 @@ void testSetTypeMismatch() {
void testAsFunctionGeneric() {
T generic<T extends Function>() {
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
Function f;
f = p.asFunction<T>(); //# 11: compile-time error
return f;
@ -173,29 +172,29 @@ void testAsFunctionGeneric() {
}
void testAsFunctionGeneric2() {
generic(ffi.Pointer<ffi.NativeFunction> p) {
generic(Pointer<NativeFunction> p) {
Function f;
f = p.asFunction<IntUnOp>(); //# 12: compile-time error
return f;
}
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
Pointer<NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
generic(p);
}
void testAsFunctionWrongNativeFunctionSignature() {
ffi.Pointer<ffi.NativeFunction<IntUnOp>> p;
Pointer<NativeFunction<IntUnOp>> p;
Function f = p.asFunction<IntUnOp>(); //# 13: compile-time error
}
typedef IntBinOp = int Function(int, int);
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
}
typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double);
typedef NativeDoubleUnOp = Double Function(Double);
typedef DoubleUnOp = double Function(double);
double myTimesThree(double d) => d * 3;
@ -203,9 +202,9 @@ double myTimesThree(double d) => d * 3;
int myTimesFour(int i) => i * 4;
void testFromFunctionGeneric() {
ffi.Pointer<ffi.NativeFunction> generic<T extends Function>(T f) {
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> result;
result = ffi.fromFunction(f); //# 70: compile-time error
Pointer<NativeFunction> generic<T extends Function>(T f) {
Pointer<NativeFunction<NativeDoubleUnOp>> result;
result = Pointer.fromFunction(f); //# 70: compile-time error
return result;
}
@ -213,9 +212,9 @@ void testFromFunctionGeneric() {
}
void testFromFunctionGeneric2() {
ffi.Pointer<ffi.NativeFunction<T>> generic<T extends Function>() {
ffi.Pointer<ffi.NativeFunction<T>> result;
result = ffi.fromFunction(myTimesThree); //# 71: compile-time error
Pointer<NativeFunction<T>> generic<T extends Function>() {
Pointer<NativeFunction<T>> result;
result = Pointer.fromFunction(myTimesThree); //# 71: compile-time error
return result;
}
@ -223,18 +222,18 @@ void testFromFunctionGeneric2() {
}
void testFromFunctionWrongNativeFunctionSignature() {
ffi.fromFunction<IntUnOp>(myTimesFour); //# 72: compile-time error
Pointer.fromFunction<IntUnOp>(myTimesFour); //# 72: compile-time error
}
void testFromFunctionTypeMismatch() {
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
p = ffi.fromFunction(myTimesFour); //# 73: compile-time error
Pointer<NativeFunction<NativeDoubleUnOp>> p;
p = Pointer.fromFunction(myTimesFour); //# 73: compile-time error
}
void testFromFunctionClosure() {
DoubleUnOp someClosure = (double z) => z / 27.0;
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
p = ffi.fromFunction(someClosure); //# 74: compile-time error
Pointer<NativeFunction<NativeDoubleUnOp>> p;
p = Pointer.fromFunction(someClosure); //# 74: compile-time error
}
class X {
@ -245,17 +244,18 @@ DoubleUnOp fld = null;
void testFromFunctionTearOff() {
fld = X().tearoff;
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
p = ffi.fromFunction(fld); //# 75: compile-time error
Pointer<NativeFunction<NativeDoubleUnOp>> p;
p = Pointer.fromFunction(fld); //# 75: compile-time error
}
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() {
Function generic<T extends Function>() {
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
Function result;
result = l.lookupFunction<T, DoubleUnOp>("cos"); //# 15: compile-time error
return result;
@ -266,7 +266,7 @@ void testLookupFunctionGeneric() {
void testLookupFunctionGeneric2() {
Function generic<T extends Function>() {
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
Function result;
result = //# 16: compile-time error
l.lookupFunction<NativeDoubleUnOp, T>("cos"); //# 16: compile-time error
@ -277,40 +277,40 @@ void testLookupFunctionGeneric2() {
}
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
}
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
}
// TODO(dacoharkes): make the next 4 test compile errors
typedef Invalid1 = int Function(ffi.Int8);
typedef Invalid2 = ffi.Int8 Function(int);
typedef Invalid3 = ffi.Int8 Function({ffi.Int8 named});
typedef Invalid4 = ffi.Int8 Function([ffi.Int8 positional]);
typedef Invalid1 = int Function(Int8);
typedef Invalid2 = Int8 Function(int);
typedef Invalid3 = Int8 Function({Int8 named});
typedef Invalid4 = Int8 Function([Int8 positional]);
void testNativeFunctionSignatureInvalidReturn() {
// ffi.Pointer<ffi.NativeFunction<Invalid1>> p = ffi.fromAddress(999);
// Pointer<NativeFunction<Invalid1>> p = fromAddress(999);
}
void testNativeFunctionSignatureInvalidParam() {
// ffi.Pointer<ffi.NativeFunction<Invalid2>> p = ffi.fromAddress(999);
// Pointer<NativeFunction<Invalid2>> p = fromAddress(999);
}
void testNativeFunctionSignatureInvalidOptionalNamed() {
// ffi.Pointer<ffi.NativeFunction<Invalid3>> p = ffi.fromAddress(999);
// Pointer<NativeFunction<Invalid3>> p = fromAddress(999);
}
void testNativeFunctionSignatureInvalidOptionalPositional() {
// ffi.Pointer<ffi.NativeFunction<Invalid4>> p = ffi.fromAddress(999);
// Pointer<NativeFunction<Invalid4>> p = fromAddress(999);
}
// error on missing field annotation
class TestStruct extends ffi.Struct<TestStruct> {
@ffi.Double()
class TestStruct extends Struct<TestStruct> {
@Double()
double x;
double y; //# 50: compile-time error
@ -320,55 +320,55 @@ class TestStruct extends ffi.Struct<TestStruct> {
class TestStruct3 extends TestStruct {} //# 52: compile-time error
// error on double annotation
class TestStruct4 extends ffi.Struct<TestStruct4> {
@ffi.Double()
@ffi.Double() //# 53: compile-time error
class TestStruct4 extends Struct<TestStruct4> {
@Double()
@Double() //# 53: compile-time error
double z;
}
// error on annotation not matching up
class TestStruct5 extends ffi.Struct<TestStruct5> {
@ffi.Int64() //# 54: compile-time error
class TestStruct5 extends Struct<TestStruct5> {
@Int64() //# 54: compile-time error
double z; //# 54: compile-time error
}
// error on annotation not matching up
class TestStruct6 extends ffi.Struct<TestStruct6> {
@ffi.Void() //# 55: compile-time error
class TestStruct6 extends Struct<TestStruct6> {
@Void() //# 55: compile-time error
double z; //# 55: compile-time error
}
// error on annotation not matching up
class TestStruct7 extends ffi.Struct<TestStruct7> {
@ffi.NativeType() //# 56: compile-time error
class TestStruct7 extends Struct<TestStruct7> {
@NativeType() //# 56: compile-time error
double z; //# 56: compile-time error
}
// error on field initializer on field
class TestStruct8 extends ffi.Struct<TestStruct8> {
@ffi.Double() //# 57: compile-time error
class TestStruct8 extends Struct<TestStruct8> {
@Double() //# 57: compile-time error
double z = 10.0; //# 57: compile-time error
}
// error on field initializer in constructor
class TestStruct9 extends ffi.Struct<TestStruct9> {
@ffi.Double()
class TestStruct9 extends Struct<TestStruct9> {
@Double()
double z;
TestStruct9() : z = 0.0 {} //# 58: compile-time error
}
// 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.
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
// annotation).
class TestStruct12 extends ffi.Struct<TestStruct12> {
@ffi.Pointer //# 61: compile-time error
class TestStruct12 extends Struct<TestStruct12> {
@Pointer //# 61: compile-time error
TestStruct9 struct; //# 61: compile-time error
}
@ -377,78 +377,78 @@ class DummyAnnotation {
}
// Structs fields may have other annotations.
class TestStruct13 extends ffi.Struct<TestStruct13> {
class TestStruct13 extends Struct<TestStruct13> {
@DummyAnnotation()
@ffi.Double()
@Double()
double z;
}
// 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 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
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

View File

@ -33,15 +33,15 @@ void testStructAllocate() {
Coordinate.allocate(10.0, 10.0, nullptr.cast()).addressOf;
Pointer<Coordinate> c2 = Coordinate.allocate(20.0, 20.0, c1).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);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(30.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(20.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(10.0, currentCoordinate.x);
c1.free();
@ -54,23 +54,26 @@ void testStructFromAddress() {
Pointer<Coordinate> c1 = Pointer.allocate(count: 3);
Pointer<Coordinate> c2 = c1.elementAt(1);
Pointer<Coordinate> c3 = c1.elementAt(2);
c1.load<Coordinate>().x = 10.0;
c1.load<Coordinate>().y = 10.0;
c1.load<Coordinate>().next = c3;
c2.load<Coordinate>().x = 20.0;
c2.load<Coordinate>().y = 20.0;
c2.load<Coordinate>().next = c1;
c3.load<Coordinate>().x = 30.0;
c3.load<Coordinate>().y = 30.0;
c3.load<Coordinate>().next = c2;
c1.ref
..x = 10.0
..y = 10.0
..next = c3;
c2.ref
..x = 20.0
..y = 20.0
..next = c1;
c3.ref
..x = 30.0
..y = 30.0
..next = c2;
Coordinate currentCoordinate = c1.load();
Coordinate currentCoordinate = c1.ref;
Expect.equals(10.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(30.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(20.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(10.0, currentCoordinate.x);
c1.free();
@ -79,11 +82,11 @@ void testStructFromAddress() {
void testStructWithNulls() {
Pointer<Coordinate> coordinate =
Coordinate.allocate(10.0, 10.0, nullptr.cast<Coordinate>()).addressOf;
Expect.equals(coordinate.load<Coordinate>().next, nullptr);
coordinate.load<Coordinate>().next = coordinate;
Expect.notEquals(coordinate.load<Coordinate>().next, nullptr);
coordinate.load<Coordinate>().next = nullptr.cast();
Expect.equals(coordinate.load<Coordinate>().next, nullptr);
Expect.equals(coordinate.ref.next, nullptr);
coordinate.ref.next = coordinate;
Expect.notEquals(coordinate.ref.next, nullptr);
coordinate.ref.next = nullptr.cast();
Expect.equals(coordinate.ref.next, nullptr);
coordinate.free();
}
@ -91,11 +94,11 @@ void testBareStruct() {
int structSize = sizeOf<Double>() * 2 + sizeOf<IntPtr>();
bare.Coordinate c1 = Pointer<Uint8>.allocate(count: structSize * 3)
.cast<bare.Coordinate>()
.load();
.ref;
bare.Coordinate c2 =
c1.addressOf.offsetBy(structSize).cast<bare.Coordinate>().load();
c1.addressOf.offsetBy(structSize).cast<bare.Coordinate>().ref;
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.y = 10.0;
c1.next = c3.addressOf;
@ -108,11 +111,11 @@ void testBareStruct() {
bare.Coordinate currentCoordinate = c1;
Expect.equals(10.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(30.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(20.0, currentCoordinate.x);
currentCoordinate = currentCoordinate.next.load();
currentCoordinate = currentCoordinate.next.ref;
Expect.equals(10.0, currentCoordinate.x);
c1.addressOf.free();

View File

@ -5,19 +5,18 @@
library Utf8;
import 'dart:convert';
import 'dart:ffi' as ffi;
import 'dart:ffi' show Pointer;
import 'dart:ffi';
/// Sample non-struct Pointer wrapper for dart:ffi library.
class Utf8 extends ffi.Struct<Utf8> {
@ffi.Uint8()
class Utf8 extends Struct<Utf8> {
@Uint8()
int char;
static String fromUtf8(Pointer<Utf8> str) {
List<int> units = [];
int len = 0;
while (true) {
int char = str.elementAt(len++).load<Utf8>().char;
int char = str[len++].char;
if (char == 0) break;
units.add(char);
}
@ -29,9 +28,9 @@ class Utf8 extends ffi.Struct<Utf8> {
Pointer<Utf8> result =
Pointer<Utf8>.allocate(count: units.length + 1).cast();
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;
}
}