[samples] Migrate ffi samples to NNBD

Closes: https://github.com/dart-lang/sdk/issues/43600.

TEST=samples/ffi

Change-Id: I620e6a73c8e37dd72f8f3921fa37dd4f8966e45c
Cq-Include-Trybots: luci.dart.try:vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,dart-sdk-linux-try,analyzer-nnbd-linux-release-try,analyzer-linux-release-try,front-end-nnbd-linux-release-x64-try,front-end-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/173542
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
This commit is contained in:
Daco Harkes 2020-11-24 18:50:28 +00:00 committed by commit-bot@chromium.org
parent 1245a196ce
commit da008fb3fc
32 changed files with 53 additions and 166 deletions

View file

@ -6,8 +6,6 @@
//
// SharedObjects=ffi_test_dynamic_library ffi_test_functions
// @dart = 2.9
import 'sample_async_callback.dart' as sample0;
import 'sample_native_port_call.dart' as sample1;

View file

@ -8,8 +8,6 @@
//
// TODO(dartbug.com/37022): Update this when we get real async callbacks.
// @dart = 2.9
import 'dart:ffi';
import 'dart:isolate';

View file

@ -16,8 +16,6 @@
// The advantage is that finalizers can be used when passing ownership of data
// (buffers) from C to Dart.
// @dart = 2.9
import 'dart:ffi';
import 'dart:isolate';
import 'dart:typed_data';
@ -79,8 +77,8 @@ void myCallback2(int a) {
}
class CppRequest {
final SendPort replyPort;
final int pendingCall;
final SendPort? replyPort;
final int? pendingCall;
final String method;
final Uint8List data;
@ -114,9 +112,9 @@ void handleCppRequests(dynamic message) {
final int argument = cppRequest.data[0];
final int result = myCallback1(argument);
final cppResponse =
CppResponse(cppRequest.pendingCall, Uint8List.fromList([result]));
CppResponse(cppRequest.pendingCall!, Uint8List.fromList([result]));
print('Dart: Responding: $cppResponse');
cppRequest.replyPort.send(cppResponse.toCppMessage());
cppRequest.replyPort!.send(cppResponse.toCppMessage());
} else if (cppRequest.method == 'myCallback2') {
final int argument = cppRequest.data[0];
myCallback2(argument);

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import "package:ffi/ffi.dart";
@ -11,12 +9,12 @@ import "package:ffi/ffi.dart";
/// Sample struct for dart:ffi library.
class Coordinate extends Struct {
@Double()
double x;
external double x;
@Double()
double y;
external double y;
Pointer<Coordinate> next;
external Pointer<Coordinate> next;
factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
return allocate<Coordinate>().ref

View file

@ -2,13 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'dart:io' show Platform;
String _platformPath(String name, {String path}) {
if (path == null) path = "";
String _platformPath(String name, String path) {
if (Platform.isLinux || Platform.isAndroid)
return path + "lib" + name + ".so";
if (Platform.isMacOS) return path + "lib" + name + ".dylib";
@ -16,7 +13,7 @@ String _platformPath(String name, {String path}) {
throw Exception("Platform not implemented");
}
DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
String fullPath = _platformPath(name, path: path);
DynamicLibrary dlopenPlatformSpecific(String name, {String path = ""}) {
String fullPath = _platformPath(name, path);
return DynamicLibrary.open(fullPath);
}

View file

@ -4,8 +4,6 @@
//
// Explicit pool used for managing resources.
// @dart = 2.9
import "dart:async";
import 'dart:convert';
import 'dart:ffi';

View file

@ -4,8 +4,6 @@
//
// Sample illustrating resources are not cleaned up when isolate is shutdown.
// @dart = 2.9
import 'dart:io';
import "dart:isolate";
import 'dart:ffi';
@ -24,7 +22,7 @@ void main() {
receiveFromHelper.sendPort,
);
print("Main: Helper started.");
Pointer<SomeResource> resource;
Pointer<SomeResource> resource = nullptr;
receiveFromHelper.listen((message) {
if (message is int) {
resource = Pointer<SomeResource>.fromAddress(message);

View file

@ -4,8 +4,6 @@
//
// Sample illustrating resource management with an explicit pool.
// @dart = 2.9
import 'dart:ffi';
import 'package:expect/expect.dart';

View file

@ -4,8 +4,6 @@
//
// Sample illustrating resource management with an implicit pool in the zone.
// @dart = 2.9
import 'dart:ffi';
import 'package:expect/expect.dart';

View file

@ -6,8 +6,6 @@
//
// SharedObjects=ffi_test_dynamic_library ffi_test_functions
// @dart = 2.9
import 'pool_isolate_shutdown_sample.dart' as pool_isolate;
import 'pool_sample.dart' as pool;
import 'pool_zoned_sample.dart' as pool_zoned;

View file

@ -4,8 +4,6 @@
//
// Sample illustrating manual resource management, not advised.
// @dart = 2.9
import 'dart:ffi';
import 'package:expect/expect.dart';

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'package:ffi/ffi.dart';
@ -20,7 +18,7 @@ import 'package:expect/expect.dart';
/// } ScreenCellAttrs;
class ScreenCellAttrs extends Struct {
@Int16()
int bits;
external int bits;
int get bold => getBits(kBoldFieldOffset, kBoldFieldLength);
void set bold(int value) =>

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'package:ffi/ffi.dart';

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'dylib_utils.dart';

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'package:ffi/ffi.dart';
@ -201,46 +199,6 @@ main() {
print(result.value);
}
{
// Passing in null for an int argument throws a null pointer exception.
BinaryOp sumPlus42 =
ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
int x = null;
try {
sumPlus42(43, x);
} on Error {
print('Expected exception on passing null for int');
}
}
{
// Passing in null for a double argument throws a null pointer exception.
DoubleUnaryOp times1_337Double = ffiTestFunctions
.lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
double x = null;
try {
times1_337Double(x);
} on Error {
print('Expected exception on passing null for double');
}
}
{
// Passing in null for an int argument throws a null pointer exception.
VigesimalOp sumManyNumbers = ffiTestFunctions
.lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
int x = null;
try {
sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13,
14.0, 15, 16.0, 17, 18.0, x, 20.0);
} on Error {
print('Expected exception on passing null for int');
}
}
{
// Passing in nullptr for a pointer argument results in a nullptr in c.
Int64PointerUnOp nullableInt64ElemAt1 =

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'coordinate.dart';

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'package:expect/expect.dart';

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'coordinate.dart';

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'package:ffi/ffi.dart';

View file

@ -6,8 +6,6 @@
//
// SharedObjects=ffi_test_dynamic_library ffi_test_functions
// @dart = 2.9
import 'sample_ffi_bitfield.dart' as bitfield;
import 'sample_ffi_data.dart' as data;
import 'sample_ffi_dynamic_library.dart' as dynamic_library;

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import "../lib/sqlite.dart";
void main() {

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
/// A synchronous SQLite wrapper.
///
/// Written using dart:ffi.

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import "dart:ffi";
import "package:ffi/ffi.dart";
@ -13,7 +11,7 @@ import "signatures.dart";
import "types.dart";
class _SQLiteBindings {
DynamicLibrary sqlite;
late DynamicLibrary sqlite;
/// Opening A New Database Connection
///
@ -29,10 +27,13 @@ class _SQLiteBindings {
/// [sqlite3_errmsg] or sqlite3_errmsg16() routines can be used to obtain
/// an English language description of the error following a failure of any
/// of the sqlite3_open() routines.
int Function(Pointer<Utf8> filename, Pointer<Pointer<Database>> databaseOut,
int flags, Pointer<Utf8> vfs) sqlite3_open_v2;
late int Function(
Pointer<Utf8> filename,
Pointer<Pointer<Database>> databaseOut,
int flags,
Pointer<Utf8> vfs) sqlite3_open_v2;
int Function(Pointer<Database> database) sqlite3_close_v2;
late int Function(Pointer<Database> database) sqlite3_close_v2;
/// Compiling An SQL Statement
///
@ -81,7 +82,7 @@ class _SQLiteBindings {
/// that is returned (the sqlite3_stmt object) contains a copy of the
/// original SQL text. This causes the [sqlite3_step] interface to
/// behave differently in three ways:
int Function(
late int Function(
Pointer<Database> database,
Pointer<Utf8> query,
int nbytes,
@ -164,7 +165,7 @@ class _SQLiteBindings {
/// of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
/// then the more specific [error codes] are returned directly
/// by sqlite3_step(). The use of the "v2" interface is recommended.
int Function(Pointer<Statement> statement) sqlite3_step;
late int Function(Pointer<Statement> statement) sqlite3_step;
/// CAPI3REF: Reset A Prepared Statement Object
///
@ -187,7 +188,7 @@ class _SQLiteBindings {
/// [sqlite3_reset] returns an appropriate [Errors].
///
/// ^The [sqlite3_reset] interface does not change the values
int Function(Pointer<Statement> statement) sqlite3_reset;
late int Function(Pointer<Statement> statement) sqlite3_reset;
/// Destroy A Prepared Statement Object
///
@ -212,14 +213,14 @@ class _SQLiteBindings {
/// a prepared statement after it has been finalized. Any use of a prepared
/// statement after it has been finalized can result in undefined and
/// undesirable behavior such as segfaults and heap corruption.
int Function(Pointer<Statement> statement) sqlite3_finalize;
late int Function(Pointer<Statement> statement) sqlite3_finalize;
/// Number Of Columns In A Result Set
///
/// ^Return the number of columns in the result set returned by the
/// prepared statement. ^This routine returns 0 if pStmt is an SQL
/// statement that does not return data (for example an [UPDATE]).
int Function(Pointer<Statement> statement) sqlite3_column_count;
late int Function(Pointer<Statement> statement) sqlite3_column_count;
/// Column Names In A Result Set
///
@ -244,7 +245,7 @@ class _SQLiteBindings {
/// ^The name of a result column is the value of the "AS" clause for
/// that column, if there is an AS clause. If there is no AS clause
/// then the name of the column is unspecified and may change from
Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
late Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
sqlite3_column_name;
/// CAPI3REF: Declared Datatype Of A Query Result
@ -274,28 +275,28 @@ class _SQLiteBindings {
/// strongly typed, but the typing is dynamic not static. ^Type
/// is associated with individual values, not with the containers
/// used to hold those values.
Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
late Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
sqlite3_column_decltype;
int Function(Pointer<Statement> statement, int columnIndex)
late int Function(Pointer<Statement> statement, int columnIndex)
sqlite3_column_type;
Pointer<Value> Function(Pointer<Statement> statement, int columnIndex)
late Pointer<Value> Function(Pointer<Statement> statement, int columnIndex)
sqlite3_column_value;
double Function(Pointer<Statement> statement, int columnIndex)
late double Function(Pointer<Statement> statement, int columnIndex)
sqlite3_column_double;
int Function(Pointer<Statement> statement, int columnIndex)
late int Function(Pointer<Statement> statement, int columnIndex)
sqlite3_column_int;
Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
late Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
sqlite3_column_text;
/// The sqlite3_errstr() interface returns the English-language text that
/// describes the result code, as UTF-8. Memory to hold the error message
/// string is managed internally and must not be freed by the application.
Pointer<Utf8> Function(int code) sqlite3_errstr;
late Pointer<Utf8> Function(int code) sqlite3_errstr;
/// Error Codes And Messages
///
@ -328,7 +329,7 @@ class _SQLiteBindings {
/// If an interface fails with SQLITE_MISUSE, that means the interface
/// was invoked incorrectly by the application. In that case, the
/// error code and message may or may not be set.
Pointer<Utf8> Function(Pointer<Database> database) sqlite3_errmsg;
late Pointer<Utf8> Function(Pointer<Database> database) sqlite3_errmsg;
_SQLiteBindings() {
sqlite = dlopenPlatformSpecific("sqlite3");
@ -392,5 +393,5 @@ class _SQLiteBindings {
}
}
_SQLiteBindings _cachedBindings;
_SQLiteBindings? _cachedBindings;
_SQLiteBindings get bindings => _cachedBindings ??= _SQLiteBindings();

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
/// Result Codes
///
/// Many SQLite functions return an integer result code from the set shown

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import "dart:ffi";
import "package:ffi/ffi.dart";

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import "dart:ffi";
/// Database Connection Handle

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
/// This iterator should be [close]d after use.
///
/// [ClosableIterator]s often use resources which should be freed after use.

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import "dart:collection";
import "dart:ffi";
@ -23,7 +21,7 @@ import "collections/closable_iterator.dart";
///
/// This database interacts with SQLite synchonously.
class Database {
Pointer<types.Database> _database;
late Pointer<types.Database> _database;
bool _open = false;
/// Open a database located at the file [path].
@ -108,11 +106,8 @@ class Database {
return Result._(this, statement, columnIndices);
}
SQLiteException _loadError([int errorCode]) {
SQLiteException _loadError(int errorCode) {
String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString();
if (errorCode == null) {
return SQLiteException(errorMessage);
}
String errorCodeExplanation =
bindings.sqlite3_errstr(errorCode).ref.toString();
return SQLiteException(
@ -126,18 +121,13 @@ class Database {
/// Please note that this iterator should be [close]d manually if not all [Row]s
/// are consumed.
class Result extends IterableBase<Row> implements ClosableIterable<Row> {
final Database _database;
final ClosableIterator<Row> _iterator;
final Pointer<Statement> _statement;
final Map<String, int> _columnIndices;
Row _currentRow = null;
Result._(
this._database,
this._statement,
this._columnIndices,
) : _iterator = _ResultIterator(_statement, _columnIndices) {}
Database database,
Pointer<Statement> statement,
Map<String, int> columnIndices,
) : _iterator = _ResultIterator(statement, columnIndices) {}
void close() => _iterator.close();
@ -148,7 +138,7 @@ class _ResultIterator implements ClosableIterator<Row> {
final Pointer<Statement> _statement;
final Map<String, int> _columnIndices;
Row _currentRow = null;
Row? _currentRow;
bool _closed = false;
_ResultIterator(this._statement, this._columnIndices) {}
@ -172,7 +162,7 @@ class _ResultIterator implements ClosableIterator<Row> {
if (_closed) {
throw SQLiteException("The result has already been closed.");
}
return _currentRow;
return _currentRow!;
}
void close() {
@ -197,7 +187,7 @@ class Row {
/// for the column by the query compiler.
dynamic readColumn(String columnName,
{Convert convert = Convert.DynamicType}) {
return readColumnByIndex(_columnIndices[columnName], convert: convert);
return readColumnByIndex(_columnIndices[columnName]!, convert: convert);
}
/// Reads column [columnName].
@ -227,7 +217,6 @@ class Row {
return readColumnByIndexAsText(columnIndex);
case Type.Null:
return null;
break;
default:
}
}
@ -235,7 +224,7 @@ class Row {
/// Reads column [columnName] and converts to [Type.Integer] if not an
/// integer.
int readColumnAsInt(String columnName) {
return readColumnByIndexAsInt(_columnIndices[columnName]);
return readColumnByIndexAsInt(_columnIndices[columnName]!);
}
/// Reads column [columnIndex] and converts to [Type.Integer] if not an
@ -247,7 +236,7 @@ class Row {
/// Reads column [columnName] and converts to [Type.Text] if not text.
String readColumnAsText(String columnName) {
return readColumnByIndexAsText(_columnIndices[columnName]);
return readColumnByIndexAsText(_columnIndices[columnName]!);
}
/// Reads column [columnIndex] and converts to [Type.Text] if not text.
@ -298,7 +287,6 @@ Type _typeFromText(String textRepresentation) {
case "null":
return Type.Null;
}
if (textRepresentation == null) return Type.Null;
throw Exception("Unknown type [$textRepresentation]");
}

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import "dart:async";
import "dart:ffi";

View file

@ -2,13 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:ffi';
import 'dart:io' show Platform;
String _platformPath(String name, {String path}) {
if (path == null) path = "";
String _platformPath(String name, String path) {
if (Platform.isLinux || Platform.isAndroid)
return path + "lib" + name + ".so";
if (Platform.isMacOS) return path + "lib" + name + ".dylib";
@ -16,7 +13,7 @@ String _platformPath(String name, {String path}) {
throw Exception("Platform not implemented");
}
DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
String fullPath = _platformPath(name, path: path);
DynamicLibrary dlopenPlatformSpecific(String name, {String path = ""}) {
String fullPath = _platformPath(name, path);
return DynamicLibrary.open(fullPath);
}

View file

@ -4,8 +4,8 @@ description: >-
Sqlite3 wrapper. Demo for dart:ffi.
author: Daco Harkes <dacoharkes@google.com>, Samir Jindel <sjindel@google.com>
environment:
sdk: '>=2.1.0 <3.0.0'
sdk: '>=2.12.0-0 <3.0.0'
dependencies:
ffi: ^0.1.3
ffi: ^0.2.0-nullsafety.1
dev_dependencies:
test: ^1.5.3
test: ^1.16.0-nullsafety.12

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
// VMOptions=--optimization-counter-threshold=5
import "dart:ffi";
@ -49,8 +47,7 @@ void main() {
expect(true, 1 <= id && id <= 3);
String name = r.readColumnByIndex(1);
expect(true, name is String);
String alternativeName = r.readColumn("alternative_name");
expect(true, alternativeName is String || alternativeName == null);
final alternativeName = r.readColumn("alternative_name") as String?;
dynamic multiTypedValue = r.readColumn("multi_typed_column");
expect(
true,
@ -76,8 +73,7 @@ void main() {
expect(true, 1 <= id && id <= 3);
String name = r.readColumnByIndex(1);
expect(true, name is String);
String alternativeName = r.readColumn("alternative_name");
expect(true, alternativeName is String || alternativeName == null);
final alternativeName = r.readColumn("alternative_name") as String?;
dynamic multiTypedValue = r.readColumn("multi_typed_column");
expect(
true,