Skip to content

Commit 14f6da1

Browse files
authored
Support @Native fields and addressOf (#860)
1 parent 0605d9a commit 14f6da1

27 files changed

+483
-159
lines changed

.github/workflows/ffigen.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ jobs:
2828
strategy:
2929
fail-fast: false
3030
matrix:
31-
sdk: [3.2.0]
31+
sdk: [dev]
32+
# sdk: [3.3.0]
3233
steps:
3334
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
3435
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
@@ -56,7 +57,7 @@ jobs:
5657
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
5758
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
5859
with:
59-
sdk: 3.2.0
60+
sdk: dev #3.3.0
6061
- name: Install dependencies
6162
run: dart pub get
6263
- name: Install libclang-14-dev
@@ -77,7 +78,7 @@ jobs:
7778
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
7879
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
7980
with:
80-
sdk: 3.2.0
81+
sdk: dev #3.3.0
8182
- name: Install dependencies
8283
run: dart pub get
8384
- name: Build test dylib and bindings
@@ -110,7 +111,7 @@ jobs:
110111
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
111112
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
112113
with:
113-
sdk: 3.2.0
114+
sdk: dev #3.3.0
114115
- name: Install dependencies
115116
run: dart pub get
116117
- name: Build test dylib and bindings

.github/workflows/ffigen_weekly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
2323
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
2424
with:
25-
sdk: 3.2.0
25+
sdk: dev #3.3.0
2626
- name: Install dependencies
2727
run: dart pub get
2828
- name: Build test dylib and bindings

.github/workflows/health.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ jobs:
1010
coverage_web: false
1111
checks: "version,changelog,license,do-not-submit,breaking"
1212
use-flutter: true
13+
sdk: master
1314
permissions:
1415
pull-requests: write

.github/workflows/publish.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ jobs:
1717
pull-requests: write # Required for writing the pull request note
1818
with:
1919
write-comments: false
20-
sdk: beta
20+
sdk: dev # use beta/stable after 3.3.0

pkgs/ffigen/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 12.0.0-dev
2+
3+
- Global variables are now compatible with the `ffi-native` option.
4+
- Exposing symbol addresses of functions and globals is now compatible with the
5+
`ffi-native` option.
6+
17
## 11.0.0
28

39
- Any compiler errors/warnings in source header files will now result in

pkgs/ffigen/example/ffinative/config.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,16 @@ headers:
99
entry-points:
1010
- 'headers/example.h'
1111
preamble: |
12+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
13+
// for details. All rights reserved. Use of this source code is governed by a
14+
// BSD-style license that can be found in the LICENSE file.
15+
1216
// ignore_for_file: deprecated_member_use
17+
functions:
18+
symbol-address:
19+
include:
20+
- sum
21+
globals:
22+
symbol-address:
23+
include:
24+
- library_version

pkgs/ffigen/example/ffinative/headers/example.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,10 @@ float *divide(int a, int b);
1616

1717
/** Divides 2 floats, returns a pointer to double. */
1818
double *dividePrecision(float a, float b);
19+
20+
int log_level = -1;
21+
22+
const int array[5] = {0, 1, 2, 3, 4};
23+
24+
/** Version of the native C library */
25+
const char* const library_version = "1.0.0-native";
Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,71 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
15
// ignore_for_file: deprecated_member_use
26

37
// AUTO GENERATED FILE, DO NOT EDIT.
48
//
59
// Generated by `package:ffigen`.
610
// ignore_for_file: type=lint
11+
@ffi.DefaultAsset('package:ffinative_example/generated_bindings.dart')
12+
library;
13+
714
import 'dart:ffi' as ffi;
15+
import '' as self;
816

917
/// Adds 2 integers.
10-
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>(
11-
symbol: 'sum', assetId: 'package:ffinative_example/generated_bindings.dart')
18+
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>()
1219
external int sum(
1320
int a,
1421
int b,
1522
);
1623

1724
/// Subtracts 2 integers.
18-
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>(
19-
symbol: 'subtract',
20-
assetId: 'package:ffinative_example/generated_bindings.dart')
25+
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>()
2126
external int subtract(
2227
int a,
2328
int b,
2429
);
2530

2631
/// Multiplies 2 integers, returns pointer to an integer,.
27-
@ffi.Native<ffi.Pointer<ffi.Int> Function(ffi.Int, ffi.Int)>(
28-
symbol: 'multiply',
29-
assetId: 'package:ffinative_example/generated_bindings.dart')
32+
@ffi.Native<ffi.Pointer<ffi.Int> Function(ffi.Int, ffi.Int)>()
3033
external ffi.Pointer<ffi.Int> multiply(
3134
int a,
3235
int b,
3336
);
3437

3538
/// Divides 2 integers, returns pointer to a float.
36-
@ffi.Native<ffi.Pointer<ffi.Float> Function(ffi.Int, ffi.Int)>(
37-
symbol: 'divide',
38-
assetId: 'package:ffinative_example/generated_bindings.dart')
39+
@ffi.Native<ffi.Pointer<ffi.Float> Function(ffi.Int, ffi.Int)>()
3940
external ffi.Pointer<ffi.Float> divide(
4041
int a,
4142
int b,
4243
);
4344

4445
/// Divides 2 floats, returns a pointer to double.
45-
@ffi.Native<ffi.Pointer<ffi.Double> Function(ffi.Float, ffi.Float)>(
46-
symbol: 'dividePrecision',
47-
assetId: 'package:ffinative_example/generated_bindings.dart')
46+
@ffi.Native<ffi.Pointer<ffi.Double> Function(ffi.Float, ffi.Float)>()
4847
external ffi.Pointer<ffi.Double> dividePrecision(
4948
double a,
5049
double b,
5150
);
51+
52+
@ffi.Native<ffi.Int>()
53+
external int log_level;
54+
55+
@ffi.Array.multi([5])
56+
@ffi.Native<ffi.Array<ffi.Int>>()
57+
external ffi.Array<ffi.Int> array;
58+
59+
/// Version of the native C library
60+
@ffi.Native<ffi.Pointer<ffi.Char>>()
61+
external final ffi.Pointer<ffi.Char> library_version;
62+
63+
const addresses = _SymbolAddresses();
64+
65+
class _SymbolAddresses {
66+
const _SymbolAddresses();
67+
ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>> get sum =>
68+
ffi.Native.addressOf(self.sum);
69+
ffi.Pointer<ffi.Pointer<ffi.Char>> get library_version =>
70+
ffi.Native.addressOf(self.library_version);
71+
}

pkgs/ffigen/example/ffinative/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
name: ffinative_example
66

77
environment:
8-
sdk: '>=3.2.0 <4.0.0'
8+
sdk: '>=3.3.0-252.0.dev <4.0.0'
99

1010
dependencies:
1111
ffi: ^2.0.1

pkgs/ffigen/lib/src/code_generator/compound.dart

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,6 @@ abstract class Compound extends BindingType {
8080
}
8181
}
8282

83-
List<int> _getArrayDimensionLengths(Type type) {
84-
final array = <int>[];
85-
var startType = type;
86-
while (startType is ConstantArray) {
87-
array.add(startType.length);
88-
startType = startType.child;
89-
}
90-
return array;
91-
}
92-
9383
String _getInlineArrayTypeString(Type type, Writer w) {
9484
if (type is ConstantArray) {
9585
return '${w.ffiLibraryPrefix}.Array<'
@@ -132,9 +122,8 @@ abstract class Compound extends BindingType {
132122
s.writeAll(m.dartDoc!.split('\n'), '\n$depth/// ');
133123
s.write('\n');
134124
}
135-
if (m.type is ConstantArray) {
136-
s.write('$depth@${w.ffiLibraryPrefix}.Array.multi(');
137-
s.write('${_getArrayDimensionLengths(m.type)})\n');
125+
if (m.type case final ConstantArray arrayType) {
126+
s.writeln(makeArrayAnnotation(w, arrayType));
138127
s.write('${depth}external ${_getInlineArrayTypeString(m.type, w)} ');
139128
s.write('${m.name};\n\n');
140129
} else {

pkgs/ffigen/lib/src/code_generator/func.dart

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,15 @@ class Func extends LookUpBinding {
145145
}
146146

147147
if (ffiNativeConfig.enabled) {
148-
final assetString = ffiNativeConfig.assetId != null
149-
? ", assetId: '${ffiNativeConfig.assetId}'"
150-
: '';
151-
final isLeafString = isLeaf ? ', isLeaf:true' : '';
152148
final nativeFuncName = needsWrapper ? funcVarName : enclosingFuncName;
153149
s.write('''
154-
@${w.ffiLibraryPrefix}.Native<$cType>(symbol: '$originalName'$assetString$isLeafString)
150+
${makeNativeAnnotation(
151+
w,
152+
nativeType: cType,
153+
dartName: nativeFuncName,
154+
nativeSymbolName: originalName,
155+
isLeaf: isLeaf,
156+
)}
155157
external $ffiReturnType $nativeFuncName($ffiArgDeclString);
156158
157159
''');
@@ -164,6 +166,15 @@ $dartReturnType $enclosingFuncName($libArg$dartArgDeclString) => $funcImplCall;
164166
165167
''');
166168
}
169+
170+
if (exposeSymbolAddress) {
171+
// Add to SymbolAddress in writer.
172+
w.symbolAddressWriter.addNativeSymbol(
173+
type:
174+
'${w.ffiLibraryPrefix}.Pointer<${w.ffiLibraryPrefix}.NativeFunction<$cType>>',
175+
name: name,
176+
);
177+
}
167178
} else {
168179
funcPointerName = w.wrapperLevelUniqueNamer.makeUnique('_${name}Ptr');
169180
final isLeafString = isLeaf ? 'isLeaf:true' : '';

pkgs/ffigen/lib/src/code_generator/global.dart

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import '../config_provider/config_types.dart';
56
import 'binding.dart';
67
import 'binding_string.dart';
78
import 'compound.dart';
9+
import 'pointer.dart';
810
import 'type.dart';
911
import 'utils.dart';
1012
import 'writer.dart';
@@ -22,6 +24,7 @@ import 'writer.dart';
2224
class Global extends LookUpBinding {
2325
final Type type;
2426
final bool exposeSymbolAddress;
27+
final FfiNativeConfig nativeConfig;
2528
final bool constant;
2629

2730
Global({
@@ -32,6 +35,7 @@ class Global extends LookUpBinding {
3235
super.dartDoc,
3336
this.exposeSymbolAddress = false,
3437
this.constant = false,
38+
this.nativeConfig = const FfiNativeConfig(enabled: false),
3539
});
3640

3741
@override
@@ -41,35 +45,63 @@ class Global extends LookUpBinding {
4145
if (dartDoc != null) {
4246
s.write(makeDartDoc(dartDoc!));
4347
}
44-
final pointerName = w.wrapperLevelUniqueNamer.makeUnique('_$globalVarName');
4548
final dartType = type.getFfiDartType(w);
4649
final cType = type.getCType(w);
4750

48-
s.write(
49-
"late final ${w.ffiLibraryPrefix}.Pointer<$cType> $pointerName = ${w.lookupFuncIdentifier}<$cType>('$originalName');\n\n");
50-
final baseTypealiasType = type.typealiasType;
51-
if (baseTypealiasType is Compound) {
52-
if (baseTypealiasType.isOpaque) {
53-
s.write(
54-
'${w.ffiLibraryPrefix}.Pointer<$cType> get $globalVarName => $pointerName;\n\n');
55-
} else {
56-
s.write('$dartType get $globalVarName => $pointerName.ref;\n\n');
51+
if (nativeConfig.enabled) {
52+
if (type case final ConstantArray arr) {
53+
s.writeln(makeArrayAnnotation(w, arr));
54+
}
55+
56+
s
57+
..writeln(makeNativeAnnotation(
58+
w,
59+
nativeType: cType,
60+
dartName: globalVarName,
61+
nativeSymbolName: originalName,
62+
isLeaf: false,
63+
))
64+
..write('external ');
65+
if (constant) {
66+
s.write('final ');
67+
}
68+
69+
s.writeln('$dartType $globalVarName;\n');
70+
71+
if (exposeSymbolAddress) {
72+
w.symbolAddressWriter.addNativeSymbol(
73+
type: '${w.ffiLibraryPrefix}.Pointer<$cType>', name: name);
5774
}
5875
} else {
59-
s.write('$dartType get $globalVarName => $pointerName.value;\n\n');
60-
if (!constant) {
61-
s.write(
62-
'set $globalVarName($dartType value) => $pointerName.value = value;\n\n');
76+
final pointerName =
77+
w.wrapperLevelUniqueNamer.makeUnique('_$globalVarName');
78+
79+
s.write(
80+
"late final ${w.ffiLibraryPrefix}.Pointer<$cType> $pointerName = ${w.lookupFuncIdentifier}<$cType>('$originalName');\n\n");
81+
final baseTypealiasType = type.typealiasType;
82+
if (baseTypealiasType is Compound) {
83+
if (baseTypealiasType.isOpaque) {
84+
s.write(
85+
'${w.ffiLibraryPrefix}.Pointer<$cType> get $globalVarName => $pointerName;\n\n');
86+
} else {
87+
s.write('$dartType get $globalVarName => $pointerName.ref;\n\n');
88+
}
89+
} else {
90+
s.write('$dartType get $globalVarName => $pointerName.value;\n\n');
91+
if (!constant) {
92+
s.write(
93+
'set $globalVarName($dartType value) => $pointerName.value = value;\n\n');
94+
}
6395
}
64-
}
6596

66-
if (exposeSymbolAddress) {
67-
// Add to SymbolAddress in writer.
68-
w.symbolAddressWriter.addSymbol(
69-
type: '${w.ffiLibraryPrefix}.Pointer<$cType>',
70-
name: name,
71-
ptrName: pointerName,
72-
);
97+
if (exposeSymbolAddress) {
98+
// Add to SymbolAddress in writer.
99+
w.symbolAddressWriter.addSymbol(
100+
type: '${w.ffiLibraryPrefix}.Pointer<$cType>',
101+
name: name,
102+
ptrName: pointerName,
103+
);
104+
}
73105
}
74106

75107
return BindingString(type: BindingStringType.global, string: s.toString());

pkgs/ffigen/lib/src/code_generator/imports.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class SelfImportedType extends Type {
7676

7777
final ffiImport = LibraryImport('ffi', 'dart:ffi');
7878
final ffiPkgImport = LibraryImport('pkg_ffi', 'package:ffi/ffi.dart');
79+
final self = LibraryImport('self', '');
7980

8081
final voidType = ImportedType(ffiImport, 'Void', 'void');
8182

0 commit comments

Comments
 (0)