From 9e596f325fbf2d87735a5a2060a1e5030bee9ed0 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Tue, 4 Jan 2022 10:29:52 +0100 Subject: [PATCH 01/10] use `Bool` --- lib/src/allocation.dart | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/src/allocation.dart b/lib/src/allocation.dart index 7c0cb4b..8c84100 100644 --- a/lib/src/allocation.dart +++ b/lib/src/allocation.dart @@ -35,9 +35,9 @@ typedef WinHeapAlloc = Pointer Function(Pointer, int, int); final WinHeapAlloc winHeapAlloc = stdlib.lookupFunction('HeapAlloc'); -typedef WinHeapFreeNative = Int32 Function( +typedef WinHeapFreeNative = Bool Function( Pointer heap, Uint32 flags, Pointer memory); -typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory); +typedef WinHeapFree = bool Function(Pointer heap, int flags, Pointer memory); final WinHeapFree winHeapFree = stdlib.lookupFunction('HeapFree'); @@ -85,12 +85,10 @@ class _MallocAllocator implements Allocator { /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be /// freed. /// - // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead - // of testing the return integer to be non-zero. @override void free(Pointer pointer) { if (Platform.isWindows) { - if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) { + if (winHeapFree(processHeap, /*flags=*/ 0, pointer)) { throw ArgumentError('Could not free $pointer.'); } } else { @@ -151,12 +149,10 @@ class _CallocAllocator implements Allocator { /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be /// freed. /// - // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead - // of testing the return integer to be non-zero. @override void free(Pointer pointer) { if (Platform.isWindows) { - if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) { + if (winHeapFree(processHeap, /*flags=*/ 0, pointer)) { throw ArgumentError('Could not free $pointer.'); } } else { From bce93b9f4b34bed85f55479f8d5eb9df54c1289e Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Tue, 4 Jan 2022 10:56:45 +0100 Subject: [PATCH 02/10] ABI-specific integers --- CHANGELOG.md | 6 ++ lib/ffi.dart | 1 + lib/src/abi_specific_ints.dart | 135 +++++++++++++++++++++++++++++++ pubspec.yaml | 4 +- test/abi_specific_ints_test.dart | 41 ++++++++++ 5 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 lib/src/abi_specific_ints.dart create mode 100644 test/abi_specific_ints_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 041d345..444d608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.2.0-dev.0 + +Added common C integer types as ABI-specific integers or typedefs. + +This pre-release requires Dart `2.16.0-118.0.dev` or greater. + ## 1.1.2 Fixed unhandled exception in `withZoneArena` (#107). diff --git a/lib/ffi.dart b/lib/ffi.dart index 774ee9e..11558f9 100644 --- a/lib/ffi.dart +++ b/lib/ffi.dart @@ -2,6 +2,7 @@ // 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. +export 'src/abi_specific_ints.dart'; export 'src/allocation.dart' show calloc, malloc; export 'src/arena.dart'; export 'src/utf8.dart'; diff --git a/lib/src/abi_specific_ints.dart b/lib/src/abi_specific_ints.dart new file mode 100644 index 0000000..a530081 --- /dev/null +++ b/lib/src/abi_specific_ints.dart @@ -0,0 +1,135 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:ffi'; + +// `int` in C. +typedef Int = Int32; + +// `unsigned int` in C. +typedef UnsignedInt = Uint32; + +// `size_t` in C. +typedef Size = UintPtr; + +// `ssize_t` in C. +typedef SSize = IntPtr; + +// `off_t` in C. +typedef Off = Long; + +/// Represents a native unsigned pointer-sized integer in C. +/// +/// [UintPtr] is not constructible in the Dart code and serves purely as marker in +/// type signatures. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint64(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint64(), +}) +class UintPtr extends AbiSpecificInteger { + const UintPtr(); +} + +/// `long` in C. +/// +/// [Long] is not constructible in the Dart code and serves purely as marker in +/// type signatures. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int32(), + Abi.androidArm64: Int64(), + Abi.androidIA32: Int32(), + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), + Abi.linuxArm: Int32(), + Abi.linuxArm64: Int64(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int64(), + Abi.macosArm64: Int64(), + Abi.macosX64: Int64(), + Abi.windowsArm64: Int32(), + Abi.windowsIA32: Int32(), + Abi.windowsX64: Int32(), +}) +class Long extends AbiSpecificInteger { + const Long(); +} + +/// `unsigned long` in C. +/// +/// [UnsignedLong] is not constructible in the Dart code and serves purely as marker in +/// type signatures. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint32(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint32(), +}) +class UnsignedLong extends AbiSpecificInteger { + const UnsignedLong(); +} + +/// `wchar_t` in C. +/// +/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as an +/// unsigned integer. +/// +/// [WChar] is not constructible in the Dart code and serves purely as marker in +/// type signatures. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint32(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint32(), + Abi.fuchsiaArm64: Uint32(), + Abi.fuchsiaX64: Uint32(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint32(), + Abi.iosX64: Uint32(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint32(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint32(), + Abi.macosArm64: Uint32(), + Abi.macosX64: Uint32(), + Abi.windowsArm64: Uint16(), + Abi.windowsIA32: Uint16(), + Abi.windowsX64: Uint16(), +}) +class WChar extends AbiSpecificInteger { + const WChar(); +} diff --git a/pubspec.yaml b/pubspec.yaml index 46c3750..7f15e92 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: ffi -version: 1.1.2 +version: 1.2.0-dev.0 homepage: https://github.com/dart-lang/ffi description: Utilities for working with Foreign Function Interface (FFI) code. environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.16.0-118.0.dev <3.0.0' dev_dependencies: test: ^1.16.0 diff --git a/test/abi_specific_ints_test.dart b/test/abi_specific_ints_test.dart new file mode 100644 index 0000000..07545fe --- /dev/null +++ b/test/abi_specific_ints_test.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:io'; + +import 'package:ffi/ffi.dart'; +import 'package:test/test.dart'; + +void main() { + test('uintptr_t', () { + expect(sizeOf(), sizeOf()); + }); + + test('wchar_t', () { + final wcharSize = sizeOf(); + if (Platform.isWindows) { + expect(wcharSize, 2); + } else { + expect(wcharSize, 4); + } + }); + + test('long', () { + final longSize = sizeOf(); + if (Platform.isWindows) { + expect(longSize, 4); + } else { + expect(longSize, sizeOf()); + } + }); + + test('unsigned long', () { + expect(sizeOf(), sizeOf()); + }); + + test('int', () { + expect(sizeOf(), sizeOf()); + }); +} From 61fb227563577d6397865619dd8344e7368c2b4a Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Tue, 4 Jan 2022 11:07:50 +0100 Subject: [PATCH 03/10] update CI --- .github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index e47bf66..ba8336d 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -46,8 +46,8 @@ jobs: fail-fast: false matrix: # Add macos-latest and/or windows-latest if relevant for this package. - os: [ubuntu-latest] - sdk: [2.12.0, dev] + os: [macos-latest, ubuntu-latest, windows-latest] + sdk: [2.16.0-124.0.dev, dev] # TODO(dacoharkes): Set to 2.16.0 after SDK release. steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 From c386bcb5e50f692a4f12370d23525072a4f68f18 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Tue, 4 Jan 2022 11:12:40 +0100 Subject: [PATCH 04/10] use `Bool` fix --- lib/src/allocation.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/allocation.dart b/lib/src/allocation.dart index 8c84100..cc2e040 100644 --- a/lib/src/allocation.dart +++ b/lib/src/allocation.dart @@ -88,7 +88,7 @@ class _MallocAllocator implements Allocator { @override void free(Pointer pointer) { if (Platform.isWindows) { - if (winHeapFree(processHeap, /*flags=*/ 0, pointer)) { + if (!winHeapFree(processHeap, /*flags=*/ 0, pointer)) { throw ArgumentError('Could not free $pointer.'); } } else { @@ -152,7 +152,7 @@ class _CallocAllocator implements Allocator { @override void free(Pointer pointer) { if (Platform.isWindows) { - if (winHeapFree(processHeap, /*flags=*/ 0, pointer)) { + if (!winHeapFree(processHeap, /*flags=*/ 0, pointer)) { throw ArgumentError('Could not free $pointer.'); } } else { From 9b561525ec7566abd7d36538a5d134473d39e42b Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Tue, 4 Jan 2022 15:27:20 +0100 Subject: [PATCH 05/10] add (unsigned) char, short, and long long --- lib/src/abi_specific_ints.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/src/abi_specific_ints.dart b/lib/src/abi_specific_ints.dart index a530081..e6dcc3c 100644 --- a/lib/src/abi_specific_ints.dart +++ b/lib/src/abi_specific_ints.dart @@ -4,12 +4,30 @@ import 'dart:ffi'; +// `char` in C. +typedef Char = Int8; + +// `unsigned char` in C. +typedef UnsignedChar = Uint8; + +// `short` in C. +typedef Short = Int16; + +// `unsigned short` in C. +typedef UnsignedShort = Uint16; + // `int` in C. typedef Int = Int32; // `unsigned int` in C. typedef UnsignedInt = Uint32; +// `long long` in C. +typedef LongLong = Int64; + +// `unsigned long long` in C. +typedef UnsignedLongLong = Uint64; + // `size_t` in C. typedef Size = UintPtr; From afd7fe207e541f7e460d7639b9031b05eb25735b Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Mon, 17 Jan 2022 16:17:49 +0100 Subject: [PATCH 06/10] Fix `char` and `wchar_t`, add `signed char` --- lib/src/abi_specific_ints.dart | 50 ++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/lib/src/abi_specific_ints.dart b/lib/src/abi_specific_ints.dart index e6dcc3c..39c06ae 100644 --- a/lib/src/abi_specific_ints.dart +++ b/lib/src/abi_specific_ints.dart @@ -4,8 +4,8 @@ import 'dart:ffi'; -// `char` in C. -typedef Char = Int8; +// `signed char` in C. +typedef SignedChar = Int8; // `unsigned char` in C. typedef UnsignedChar = Uint8; @@ -37,7 +37,35 @@ typedef SSize = IntPtr; // `off_t` in C. typedef Off = Long; -/// Represents a native unsigned pointer-sized integer in C. +/// `char` in C. +/// +/// [Char] is not constructible in the Dart code and serves purely as marker +/// in type signatures. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint8(), + Abi.androidArm64: Uint8(), + Abi.androidIA32: Uint8(), + Abi.androidX64: Uint8(), + Abi.fuchsiaArm64: Int8(), + Abi.fuchsiaX64: Int8(), + Abi.iosArm: Int8(), + Abi.iosArm64: Int8(), + Abi.iosX64: Int8(), + Abi.linuxArm: Int8(), + Abi.linuxArm64: Int8(), + Abi.linuxIA32: Int8(), + Abi.linuxX64: Int8(), + Abi.macosArm64: Int8(), + Abi.macosX64: Int8(), + Abi.windowsArm64: Int8(), + Abi.windowsIA32: Int8(), + Abi.windowsX64: Int8(), +}) +class Char extends AbiSpecificInteger { + const Char(); +} + +/// `uintptr_t` in C. /// /// [UintPtr] is not constructible in the Dart code and serves purely as marker in /// type signatures. @@ -134,16 +162,16 @@ class UnsignedLong extends AbiSpecificInteger { Abi.androidIA32: Uint32(), Abi.androidX64: Uint32(), Abi.fuchsiaArm64: Uint32(), - Abi.fuchsiaX64: Uint32(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint32(), - Abi.iosX64: Uint32(), + Abi.fuchsiaX64: Int32(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int32(), + Abi.iosX64: Int32(), Abi.linuxArm: Uint32(), Abi.linuxArm64: Uint32(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint32(), - Abi.macosArm64: Uint32(), - Abi.macosX64: Uint32(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int32(), + Abi.macosArm64: Int32(), + Abi.macosX64: Int32(), Abi.windowsArm64: Uint16(), Abi.windowsIA32: Uint16(), Abi.windowsX64: Uint16(), From d861484068081c9acfc867288368565940390568 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Mon, 17 Jan 2022 16:20:38 +0100 Subject: [PATCH 07/10] address comments --- lib/src/allocation.dart | 8 ++++---- test/abi_specific_ints_test.dart | 14 ++------------ 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/lib/src/allocation.dart b/lib/src/allocation.dart index cc2e040..49babe8 100644 --- a/lib/src/allocation.dart +++ b/lib/src/allocation.dart @@ -35,9 +35,9 @@ typedef WinHeapAlloc = Pointer Function(Pointer, int, int); final WinHeapAlloc winHeapAlloc = stdlib.lookupFunction('HeapAlloc'); -typedef WinHeapFreeNative = Bool Function( +typedef WinHeapFreeNative = Int32 Function( Pointer heap, Uint32 flags, Pointer memory); -typedef WinHeapFree = bool Function(Pointer heap, int flags, Pointer memory); +typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory); final WinHeapFree winHeapFree = stdlib.lookupFunction('HeapFree'); @@ -88,7 +88,7 @@ class _MallocAllocator implements Allocator { @override void free(Pointer pointer) { if (Platform.isWindows) { - if (!winHeapFree(processHeap, /*flags=*/ 0, pointer)) { + if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) { throw ArgumentError('Could not free $pointer.'); } } else { @@ -152,7 +152,7 @@ class _CallocAllocator implements Allocator { @override void free(Pointer pointer) { if (Platform.isWindows) { - if (!winHeapFree(processHeap, /*flags=*/ 0, pointer)) { + if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) { throw ArgumentError('Could not free $pointer.'); } } else { diff --git a/test/abi_specific_ints_test.dart b/test/abi_specific_ints_test.dart index 07545fe..cf059b0 100644 --- a/test/abi_specific_ints_test.dart +++ b/test/abi_specific_ints_test.dart @@ -14,21 +14,11 @@ void main() { }); test('wchar_t', () { - final wcharSize = sizeOf(); - if (Platform.isWindows) { - expect(wcharSize, 2); - } else { - expect(wcharSize, 4); - } + expect(sizeOf, Platform.isWindows ? 2 : 4); }); test('long', () { - final longSize = sizeOf(); - if (Platform.isWindows) { - expect(longSize, 4); - } else { - expect(longSize, sizeOf()); - } + expect(sizeOf, Platform.isWindows ? 4 : sizeOf()); }); test('unsigned long', () { From 8a95e7f3ebf6ffdef453dfef80129a70cc11b547 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Mon, 17 Jan 2022 16:31:15 +0100 Subject: [PATCH 08/10] Fix test typos --- test/abi_specific_ints_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/abi_specific_ints_test.dart b/test/abi_specific_ints_test.dart index cf059b0..8f71363 100644 --- a/test/abi_specific_ints_test.dart +++ b/test/abi_specific_ints_test.dart @@ -14,11 +14,11 @@ void main() { }); test('wchar_t', () { - expect(sizeOf, Platform.isWindows ? 2 : 4); + expect(sizeOf(), Platform.isWindows ? 2 : 4); }); test('long', () { - expect(sizeOf, Platform.isWindows ? 4 : sizeOf()); + expect(sizeOf(), Platform.isWindows ? 4 : sizeOf()); }); test('unsigned long', () { From 72aafc25c7a045f9f267c606536ee92fd6d43392 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Thu, 20 Jan 2022 15:55:34 +0100 Subject: [PATCH 09/10] update with c_type.dart from 2.17 SDK https://dart-review.googlesource.com/c/sdk/+/228541 --- lib/ffi.dart | 2 +- lib/src/abi_specific_ints.dart | 181 ------ lib/src/c_type.dart | 516 ++++++++++++++++++ ...ecific_ints_test.dart => c_type_test.dart} | 0 4 files changed, 517 insertions(+), 182 deletions(-) delete mode 100644 lib/src/abi_specific_ints.dart create mode 100644 lib/src/c_type.dart rename test/{abi_specific_ints_test.dart => c_type_test.dart} (100%) diff --git a/lib/ffi.dart b/lib/ffi.dart index 11558f9..e66c090 100644 --- a/lib/ffi.dart +++ b/lib/ffi.dart @@ -2,8 +2,8 @@ // 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. -export 'src/abi_specific_ints.dart'; export 'src/allocation.dart' show calloc, malloc; export 'src/arena.dart'; +export 'src/c_type.dart'; export 'src/utf8.dart'; export 'src/utf16.dart'; diff --git a/lib/src/abi_specific_ints.dart b/lib/src/abi_specific_ints.dart deleted file mode 100644 index 39c06ae..0000000 --- a/lib/src/abi_specific_ints.dart +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:ffi'; - -// `signed char` in C. -typedef SignedChar = Int8; - -// `unsigned char` in C. -typedef UnsignedChar = Uint8; - -// `short` in C. -typedef Short = Int16; - -// `unsigned short` in C. -typedef UnsignedShort = Uint16; - -// `int` in C. -typedef Int = Int32; - -// `unsigned int` in C. -typedef UnsignedInt = Uint32; - -// `long long` in C. -typedef LongLong = Int64; - -// `unsigned long long` in C. -typedef UnsignedLongLong = Uint64; - -// `size_t` in C. -typedef Size = UintPtr; - -// `ssize_t` in C. -typedef SSize = IntPtr; - -// `off_t` in C. -typedef Off = Long; - -/// `char` in C. -/// -/// [Char] is not constructible in the Dart code and serves purely as marker -/// in type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint8(), - Abi.androidArm64: Uint8(), - Abi.androidIA32: Uint8(), - Abi.androidX64: Uint8(), - Abi.fuchsiaArm64: Int8(), - Abi.fuchsiaX64: Int8(), - Abi.iosArm: Int8(), - Abi.iosArm64: Int8(), - Abi.iosX64: Int8(), - Abi.linuxArm: Int8(), - Abi.linuxArm64: Int8(), - Abi.linuxIA32: Int8(), - Abi.linuxX64: Int8(), - Abi.macosArm64: Int8(), - Abi.macosX64: Int8(), - Abi.windowsArm64: Int8(), - Abi.windowsIA32: Int8(), - Abi.windowsX64: Int8(), -}) -class Char extends AbiSpecificInteger { - const Char(); -} - -/// `uintptr_t` in C. -/// -/// [UintPtr] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint64(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint64(), -}) -class UintPtr extends AbiSpecificInteger { - const UintPtr(); -} - -/// `long` in C. -/// -/// [Long] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Int32(), - Abi.androidArm64: Int64(), - Abi.androidIA32: Int32(), - Abi.androidX64: Int64(), - Abi.fuchsiaArm64: Int64(), - Abi.fuchsiaX64: Int64(), - Abi.iosArm: Int32(), - Abi.iosArm64: Int64(), - Abi.iosX64: Int64(), - Abi.linuxArm: Int32(), - Abi.linuxArm64: Int64(), - Abi.linuxIA32: Int32(), - Abi.linuxX64: Int64(), - Abi.macosArm64: Int64(), - Abi.macosX64: Int64(), - Abi.windowsArm64: Int32(), - Abi.windowsIA32: Int32(), - Abi.windowsX64: Int32(), -}) -class Long extends AbiSpecificInteger { - const Long(); -} - -/// `unsigned long` in C. -/// -/// [UnsignedLong] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint32(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint32(), -}) -class UnsignedLong extends AbiSpecificInteger { - const UnsignedLong(); -} - -/// `wchar_t` in C. -/// -/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as an -/// unsigned integer. -/// -/// [WChar] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint32(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint32(), - Abi.fuchsiaArm64: Uint32(), - Abi.fuchsiaX64: Int32(), - Abi.iosArm: Int32(), - Abi.iosArm64: Int32(), - Abi.iosX64: Int32(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint32(), - Abi.linuxIA32: Int32(), - Abi.linuxX64: Int32(), - Abi.macosArm64: Int32(), - Abi.macosX64: Int32(), - Abi.windowsArm64: Uint16(), - Abi.windowsIA32: Uint16(), - Abi.windowsX64: Uint16(), -}) -class WChar extends AbiSpecificInteger { - const WChar(); -} diff --git a/lib/src/c_type.dart b/lib/src/c_type.dart new file mode 100644 index 0000000..67c5656 --- /dev/null +++ b/lib/src/c_type.dart @@ -0,0 +1,516 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This library defines [NativeType]s for common C types. +/// +/// Many C types only define a minimal size in the C standard, but they are +/// consistent per [Abi]. Therefore we use [AbiSpecificInteger]s to define +/// these C types in this library. +/// +/// These types will only be defined here for Dart 2.16 because they did not +/// make it into the `dart:ffi`. Starting with Dart 2.17 we will re-export the +/// types from the `dart:ffi` here. + +import 'dart:ffi'; + +/// The C `char` type. +/// +/// Typically a signed or unsigned 8-bit integer. +/// For a guaranteed 8-bit integer, use [Int8] with the C `int8_t` type +/// or [Uint8] with the C `uint8_t` type. +/// For a specifically `signed` or `unsigned` `char`, use [SignedChar] or +/// [UnsignedChar]. +/// +/// The [Char] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint8(), + Abi.androidArm64: Uint8(), + Abi.androidIA32: Uint8(), + Abi.androidX64: Uint8(), + Abi.fuchsiaArm64: Int8(), + Abi.fuchsiaX64: Int8(), + Abi.iosArm: Uint8(), + Abi.iosArm64: Int8(), + Abi.iosX64: Int8(), + Abi.linuxArm: Uint8(), + Abi.linuxArm64: Int8(), + Abi.linuxIA32: Int8(), + Abi.linuxX64: Int8(), + Abi.macosArm64: Int8(), + Abi.macosX64: Int8(), + Abi.windowsArm64: Int8(), + Abi.windowsIA32: Int8(), + Abi.windowsX64: Int8(), +}) +class Char extends AbiSpecificInteger { + const Char(); +} + +/// The C `signed char` type. +/// +/// Typically a signed 8-bit integer. +/// For a guaranteed 8-bit integer, use [Int8] with the C `int8_t` type. +/// For an `unsigned char`, use [UnsignedChar]. +/// +/// The [SignedChar] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int8(), + Abi.androidArm64: Int8(), + Abi.androidIA32: Int8(), + Abi.androidX64: Int8(), + Abi.fuchsiaArm64: Int8(), + Abi.fuchsiaX64: Int8(), + Abi.iosArm: Int8(), + Abi.iosArm64: Int8(), + Abi.iosX64: Int8(), + Abi.linuxArm: Int8(), + Abi.linuxArm64: Int8(), + Abi.linuxIA32: Int8(), + Abi.linuxX64: Int8(), + Abi.macosArm64: Int8(), + Abi.macosX64: Int8(), + Abi.windowsArm64: Int8(), + Abi.windowsIA32: Int8(), + Abi.windowsX64: Int8(), +}) +class SignedChar extends AbiSpecificInteger { + const SignedChar(); +} + +/// The C `unsigned char` type. +/// +/// Typically an unsigned 8-bit integer. +/// For a guaranteed 8-bit integer, use [Uint8] with the C `uint8_t` type. +/// For a `signed char`, use [Char]. +/// +/// The [UnsignedChar] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint8(), + Abi.androidArm64: Uint8(), + Abi.androidIA32: Uint8(), + Abi.androidX64: Uint8(), + Abi.fuchsiaArm64: Uint8(), + Abi.fuchsiaX64: Uint8(), + Abi.iosArm: Uint8(), + Abi.iosArm64: Uint8(), + Abi.iosX64: Uint8(), + Abi.linuxArm: Uint8(), + Abi.linuxArm64: Uint8(), + Abi.linuxIA32: Uint8(), + Abi.linuxX64: Uint8(), + Abi.macosArm64: Uint8(), + Abi.macosX64: Uint8(), + Abi.windowsArm64: Uint8(), + Abi.windowsIA32: Uint8(), + Abi.windowsX64: Uint8(), +}) +class UnsignedChar extends AbiSpecificInteger { + const UnsignedChar(); +} + +/// The C `short` type. +/// +/// Typically a signed 16-bit integer. +/// For a guaranteed 16-bit integer, use [Int16] with the C `int16_t` type. +/// For an `unsigned short`, use [UnsignedShort]. +/// +/// The [Short] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int16(), + Abi.androidArm64: Int16(), + Abi.androidIA32: Int16(), + Abi.androidX64: Int16(), + Abi.fuchsiaArm64: Int16(), + Abi.fuchsiaX64: Int16(), + Abi.iosArm: Int16(), + Abi.iosArm64: Int16(), + Abi.iosX64: Int16(), + Abi.linuxArm: Int16(), + Abi.linuxArm64: Int16(), + Abi.linuxIA32: Int16(), + Abi.linuxX64: Int16(), + Abi.macosArm64: Int16(), + Abi.macosX64: Int16(), + Abi.windowsArm64: Int16(), + Abi.windowsIA32: Int16(), + Abi.windowsX64: Int16(), +}) +class Short extends AbiSpecificInteger { + const Short(); +} + +/// The C `unsigned short` type. +/// +/// Typically an unsigned 16-bit integer. +/// For a guaranteed 16-bit integer, use [Uint16] with the C `uint16_t` type. +/// For a signed `short`, use [Short]. +/// +/// The [UnsignedShort] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint16(), + Abi.androidArm64: Uint16(), + Abi.androidIA32: Uint16(), + Abi.androidX64: Uint16(), + Abi.fuchsiaArm64: Uint16(), + Abi.fuchsiaX64: Uint16(), + Abi.iosArm: Uint16(), + Abi.iosArm64: Uint16(), + Abi.iosX64: Uint16(), + Abi.linuxArm: Uint16(), + Abi.linuxArm64: Uint16(), + Abi.linuxIA32: Uint16(), + Abi.linuxX64: Uint16(), + Abi.macosArm64: Uint16(), + Abi.macosX64: Uint16(), + Abi.windowsArm64: Uint16(), + Abi.windowsIA32: Uint16(), + Abi.windowsX64: Uint16(), +}) +class UnsignedShort extends AbiSpecificInteger { + const UnsignedShort(); +} + +/// The C `int` type. +/// +/// Typically a signed 32-bit integer. +/// For a guaranteed 32-bit integer, use [Int32] with the C `int32_t` type. +/// For an `unsigned int`, use [UnsignedInt]. +/// +/// The [Int] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int32(), + Abi.androidArm64: Int32(), + Abi.androidIA32: Int32(), + Abi.androidX64: Int32(), + Abi.fuchsiaArm64: Int32(), + Abi.fuchsiaX64: Int32(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int32(), + Abi.iosX64: Int32(), + Abi.linuxArm: Int32(), + Abi.linuxArm64: Int32(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int32(), + Abi.macosArm64: Int32(), + Abi.macosX64: Int32(), + Abi.windowsArm64: Int32(), + Abi.windowsIA32: Int32(), + Abi.windowsX64: Int32(), +}) +class Int extends AbiSpecificInteger { + const Int(); +} + +/// The C `unsigned int` type. +/// +/// Typically an unsigned 32-bit integer. +/// For a guaranteed 32-bit integer, use [Uint32] with the C `uint32_t` type. +/// For a signed `int`, use [Int]. +/// +/// The [UnsignedInt] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint32(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint32(), + Abi.fuchsiaArm64: Uint32(), + Abi.fuchsiaX64: Uint32(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint32(), + Abi.iosX64: Uint32(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint32(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint32(), + Abi.macosArm64: Uint32(), + Abi.macosX64: Uint32(), + Abi.windowsArm64: Uint32(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint32(), +}) +class UnsignedInt extends AbiSpecificInteger { + const UnsignedInt(); +} + +/// The C `long int`, aka. `long`, type. +/// +/// Typically a signed 32- or 64-bit integer. +/// For a guaranteed 32-bit integer, use [Int32] with the C `int32_t` type. +/// For a guaranteed 64-bit integer, use [Int64] with the C `int64_t` type. +/// For an `unsigned long`, use [UnsignedLong]. +/// +/// The [Long] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int32(), + Abi.androidArm64: Int64(), + Abi.androidIA32: Int32(), + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), + Abi.linuxArm: Int32(), + Abi.linuxArm64: Int64(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int64(), + Abi.macosArm64: Int64(), + Abi.macosX64: Int64(), + Abi.windowsArm64: Int32(), + Abi.windowsIA32: Int32(), + Abi.windowsX64: Int32(), +}) +class Long extends AbiSpecificInteger { + const Long(); +} + +/// The C `unsigned long int`, aka. `unsigned long`, type. +/// +/// Typically an unsigned 32- or 64-bit integer. +/// For a guaranteed 32-bit integer, use [Uint32] with the C `uint32_t` type. +/// For a guaranteed 64-bit integer, use [Uint64] with the C `uint64_t` type. +/// For a signed `long`, use [Long]. +/// +/// The [UnsignedLong] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint32(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint32(), +}) +class UnsignedLong extends AbiSpecificInteger { + const UnsignedLong(); +} + +/// The C `long long` type. +/// +/// Typically a signed 64-bit integer. +/// For a guaranteed 64-bit integer, use [Int64] with the C `int64_t` type. +/// For an `unsigned long long`, use [UnsignedLongLong]. +/// +/// The [LongLong] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int64(), + Abi.androidArm64: Int64(), + Abi.androidIA32: Int64(), + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), + Abi.iosArm: Int64(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), + Abi.linuxArm: Int64(), + Abi.linuxArm64: Int64(), + Abi.linuxIA32: Int64(), + Abi.linuxX64: Int64(), + Abi.macosArm64: Int64(), + Abi.macosX64: Int64(), + Abi.windowsArm64: Int64(), + Abi.windowsIA32: Int64(), + Abi.windowsX64: Int64(), +}) +class LongLong extends AbiSpecificInteger { + const LongLong(); +} + +/// The C `unsigned long long` type. +/// +/// Typically an unsigned 64-bit integer. +/// For a guaranteed 64-bit integer, use [Uint64] with the C `uint64_t` type. +/// For a signed `long long`, use [LongLong]. +/// +/// The [UnsignedLongLong] type is a native type, and should not be constructed +/// in Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint64(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint64(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint64(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint64(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint64(), + Abi.linuxX64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint64(), + Abi.windowsIA32: Uint64(), + Abi.windowsX64: Uint64(), +}) +class UnsignedLongLong extends AbiSpecificInteger { + const UnsignedLongLong(); +} + +/// The C `intptr_t` type. +/// +/// The [IntPtr] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int32(), + Abi.androidArm64: Int64(), + Abi.androidIA32: Int32(), + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), + Abi.linuxArm: Int32(), + Abi.linuxArm64: Int64(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int64(), + Abi.macosArm64: Int64(), + Abi.macosX64: Int64(), + Abi.windowsArm64: Int64(), + Abi.windowsIA32: Int32(), + Abi.windowsX64: Int64(), +}) +class IntPtr extends AbiSpecificInteger { + const IntPtr(); +} + +/// The C `uintptr_t` type. +/// +/// The [UintPtr] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint64(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint64(), +}) +class UintPtr extends AbiSpecificInteger { + const UintPtr(); +} + +/// The C `size_t` type. +/// +/// The [Size] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint64(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint64(), +}) +class Size extends AbiSpecificInteger { + const Size(); +} + +/// The C `wchar_t` type. +/// +/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as the +/// defaults on the tested [Abi]s. +/// +/// The [WChar] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint32(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint32(), + Abi.fuchsiaArm64: Uint32(), + Abi.fuchsiaX64: Int32(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int32(), + Abi.iosX64: Int32(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint32(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int32(), + Abi.macosArm64: Int32(), + Abi.macosX64: Int32(), + Abi.windowsArm64: Uint16(), + Abi.windowsIA32: Uint16(), + Abi.windowsX64: Uint16(), +}) +class WChar extends AbiSpecificInteger { + const WChar(); +} diff --git a/test/abi_specific_ints_test.dart b/test/c_type_test.dart similarity index 100% rename from test/abi_specific_ints_test.dart rename to test/c_type_test.dart From d295a2b1db80543593e71af6a9e7f04bd437f7c4 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Thu, 20 Jan 2022 16:00:36 +0100 Subject: [PATCH 10/10] Update changelog to document 2.16/2.17 situation --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 444d608..05ccac5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ ## 1.2.0-dev.0 -Added common C integer types as ABI-specific integers or typedefs. +Added common C integer types as ABI-specific integers. These common C integer +types will make their way into `dart:ffi` in 2.17 and be deprecated from this +package. Having them in this package enables using them in Dart 2.16. This pre-release requires Dart `2.16.0-118.0.dev` or greater.