@@ -3,9 +3,11 @@ This package provides **experimental** bindings to POSIX APIs e.g. `open`,
33
44## Why have another POSIX API implementation for Dart?
55
6- Thare are two existing packages that provide POSIX API bindings for Dart:
7- 1 . [ ` package:posix ` ] ( https://pub.dev/packages/posix )
8- 2 . [ ` package:stdlibc ` ] ( https://pub.dev/packages/stdlibc )
6+ There are two existing packages that provide POSIX API bindings for Dart:
7+ 1 . [ ` package:posix ` ]
8+ 2 . [ ` package:stdlibc ` ]
9+
10+ Both are excellent and offer easier-to-use APIs than ` package:unix_api ` .
911
1012` package:unix_api ` requires a native tool chain and has a small amount of
1113native code that cannot be tree shaken away. In exchange, it works on all
@@ -17,21 +19,22 @@ API calls as part of JIT compilation then the `errno` exported by
1719` package:unix_api ` is not affected (see the Dart SDK issue
1820[ Support for capturing errno across calls] ( https://github.com/dart-lang/sdk/issues/38832 ) ).
1921
20- | Package | Required Tools | Reliable ` errno ` | Supported Platforms | Fixed Disk Usage |
21- | :--- | :-------------- | :-------------- | :-------------------------------------- | :-------------- |
22- | ` posix ` | Dart | No | iOS (arm64), Linux (x64), macOS (arm64) | 0 KiB |
23- | ` stdlibc ` | Dart | No | iOS (arm64), Linux (x64), macOS (arm64) | 0 KiB |
24- | ` unix_api ` | Dart, C compiler | Yes | Android (x64, arm32, arm64), iOS (arm64), Linux (x64, arm64), macOS (x64, arm64) | ~ 60 KiB |
22+ | Package | Required Tools | Reliable ` errno ` | Supported Platforms | Fixed Disk Usage |
23+ | :--- | :-------------- | :-------------- | :-------------------------------------- | :-------------- |
24+ | [ ` package: posix` ] | Dart | No | iOS (arm64), Linux (x64), macOS (arm64) | 0 KiB |
25+ | [ ` package: stdlibc` ] | Dart | No | iOS (arm64), Linux (x64), macOS (arm64) | 0 KiB |
26+ | ` package: unix_api` | Dart, C compiler | Yes | Android (x64, arm32, arm64), iOS (arm64), Linux (x64, arm64), macOS (x64, arm64) | ~ 60 KiB |
2527
2628## Design
2729
2830The POSIX API is a defined in terms of source, not object compatibility.
2931
30- For example, glibc defines ` stat ` as :
32+ For example, glibc defines ` stat ` using a macro :
3133
3234` #define stat(fname, buf) __xstat (_STAT_VER, fname, buf) `
3335
34- So running ` ffigen ` on ` sys/stat.h ` will not produce an entry for ` stat ` .
36+ So using [ ` package:ffigen ` ] to generate Dart bindings for ` sys/stat.h ` will not
37+ produce an entry for ` stat ` .
3538
3639libc may also reorder ` struct ` fields across architectures, add extra
3740fields, etc. For example, the glibc definition of ` struct stat ` starts
@@ -49,23 +52,60 @@ struct stat
4952#else
5053```
5154
55+ When using [`package:ffigen`] to generate bindings for such code, separate
56+ bindings must be generated for every combination of platform (e.g.
57+ Android) and architecture (e.g. arm64).
5258
5359`package:unix_api` works around this problem by defining a native (C) function
5460for every POSIX function. The native function just calls the corresponding
55- POSIX function. For example:
61+ POSIX function while preserving `errno` by passing a reference to it explicitly.
62+ For example:
5663
5764```c
58- int libc_shim_rename(const char *old, const char *newy) {
59- return rename(old, newy);
65+ int libc_shim_rename(const char * arg0, const char * arg1, int * err) {
66+ int r;
67+ errno = *err;
68+ r = rename(arg0, arg1);
69+ *err = errno;
70+ return r;
6071}
6172```
6273
6374This allows the platforms C compiler to deal with macro expansions,
64- platform-specific struct layout, etc.
75+ platform-specific struct layout, etc. [ `package: hooks '] is used to
76+ transparently compile the C code on the developer's behalf.
77+
78+ Then ` package:unix_api ` uses ` package:ffigen ` to generate Dart bindings to
79+ these functions. For example:
80+
81+ ``` dart
82+ // ffigen'd bindings
83+ @ffi.Native<
84+ ffi.Int Function(
85+ ffi.Pointer<ffi.Char>,
86+ ffi.Pointer<ffi.Char>,
87+ ffi.Pointer<ffi.Int>,
88+ )
89+ >()
90+ external int libc_shim_rename(
91+ ffi.Pointer<ffi.Char> arg0,
92+ ffi.Pointer<ffi.Char> arg1,
93+ ffi.Pointer<ffi.Int> arg2,
94+ );
95+ ```
6596
66- Then ` package:unix_api ` uses ` package:ffigen ` to provide Dart bindings to
67- these functions.
97+ And finally, ` package:unix_api ` provides a function that provides the public
98+ interface. For example:
6899
100+ ``` dart
101+ /// Renames a file.
102+ ///
103+ /// See the [POSIX specification for `rename`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html).
104+ int rename(ffi.Pointer<ffi.Char> arg0, ffi.Pointer<ffi.Char> arg1) =>
105+ libc_shim_rename(arg0, arg1, errnoPtr);
106+ ```
107+
108+ ` errno ` is implemented [ locally in the package] ( lib/src/errno.dart ) .
69109
70110## Status: Experimental
71111
@@ -81,3 +121,8 @@ much higher expected rate of API and breaking changes.
81121Your feedback is valuable and will help us evolve this package. For general
82122feedback, suggestions, and comments, please file an issue in the
83123[ bug tracker] ( https://github.com/dart-lang/labs/issues ) .
124+
125+ [ `package:ffigen` ] : https://pub.dev/packages/ffigen
126+ [ `package:hooks` ] : https://pub.dev/packages/hooks
127+ [ `package:posix` ] : https://pub.dev/packages/posix
128+ [ `package:stdlibc` ] : https://pub.dev/packages/stdlibc
0 commit comments