Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @Native fields and addressOf #860

Merged
merged 23 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/ffigen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ jobs:
strategy:
fail-fast: false
matrix:
sdk: [3.2.0]
sdk: [dev]
# sdk: [3.3.0]
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
Expand Down Expand Up @@ -56,7 +57,7 @@ jobs:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
with:
sdk: 3.2.0
sdk: dev #3.3.0
- name: Install dependencies
run: dart pub get
- name: Install libclang-14-dev
Expand All @@ -77,7 +78,7 @@ jobs:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
with:
sdk: 3.2.0
sdk: dev #3.3.0
- name: Install dependencies
run: dart pub get
- name: Build test dylib and bindings
Expand Down Expand Up @@ -110,7 +111,7 @@ jobs:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
with:
sdk: 3.2.0
sdk: dev #3.3.0
- name: Install dependencies
run: dart pub get
- name: Build test dylib and bindings
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ffigen_weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
with:
sdk: 3.2.0
sdk: dev #3.3.0
- name: Install dependencies
run: dart pub get
- name: Build test dylib and bindings
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/health.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ jobs:
coverage_web: false
checks: "version,changelog,license,do-not-submit,breaking"
use-flutter: true
sdk: master
permissions:
pull-requests: write
2 changes: 1 addition & 1 deletion .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
pull-requests: write # Required for writing the pull request note
with:
write-comments: false
sdk: beta
sdk: dev # use beta/stable after 3.3.0
6 changes: 6 additions & 0 deletions pkgs/ffigen/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 12.0.0-dev

- Global variables are now compatible with the `ffi-native` option.
- Exposing symbol addresses of functions and globals is now compatible with the
`ffi-native` option.

## 11.0.0

- Any compiler errors/warnings in source header files will now result in
Expand Down
12 changes: 12 additions & 0 deletions pkgs/ffigen/example/ffinative/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,16 @@ headers:
entry-points:
- 'headers/example.h'
preamble: |
// Copyright (c) 2020, 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.

// ignore_for_file: deprecated_member_use
functions:
symbol-address:
include:
- sum
globals:
symbol-address:
include:
- library_version
7 changes: 7 additions & 0 deletions pkgs/ffigen/example/ffinative/headers/example.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,10 @@ float *divide(int a, int b);

/** Divides 2 floats, returns a pointer to double. */
double *dividePrecision(float a, float b);

int log_level = -1;

const int array[5] = {0, 1, 2, 3, 4};

/** Version of the native C library */
const char* const library_version = "1.0.0-native";
48 changes: 34 additions & 14 deletions pkgs/ffigen/example/ffinative/lib/generated_bindings.dart
Original file line number Diff line number Diff line change
@@ -1,51 +1,71 @@
// Copyright (c) 2020, 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.

// ignore_for_file: deprecated_member_use

// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
// ignore_for_file: type=lint
@ffi.DefaultAsset('package:ffinative_example/generated_bindings.dart')
library;

import 'dart:ffi' as ffi;
import '' as self;

/// Adds 2 integers.
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>(
symbol: 'sum', assetId: 'package:ffinative_example/generated_bindings.dart')
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>()
external int sum(
int a,
int b,
);

/// Subtracts 2 integers.
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>(
symbol: 'subtract',
assetId: 'package:ffinative_example/generated_bindings.dart')
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int)>()
external int subtract(
int a,
int b,
);

/// Multiplies 2 integers, returns pointer to an integer,.
@ffi.Native<ffi.Pointer<ffi.Int> Function(ffi.Int, ffi.Int)>(
symbol: 'multiply',
assetId: 'package:ffinative_example/generated_bindings.dart')
@ffi.Native<ffi.Pointer<ffi.Int> Function(ffi.Int, ffi.Int)>()
external ffi.Pointer<ffi.Int> multiply(
int a,
int b,
);

/// Divides 2 integers, returns pointer to a float.
@ffi.Native<ffi.Pointer<ffi.Float> Function(ffi.Int, ffi.Int)>(
symbol: 'divide',
assetId: 'package:ffinative_example/generated_bindings.dart')
@ffi.Native<ffi.Pointer<ffi.Float> Function(ffi.Int, ffi.Int)>()
external ffi.Pointer<ffi.Float> divide(
int a,
int b,
);

/// Divides 2 floats, returns a pointer to double.
@ffi.Native<ffi.Pointer<ffi.Double> Function(ffi.Float, ffi.Float)>(
symbol: 'dividePrecision',
assetId: 'package:ffinative_example/generated_bindings.dart')
@ffi.Native<ffi.Pointer<ffi.Double> Function(ffi.Float, ffi.Float)>()
external ffi.Pointer<ffi.Double> dividePrecision(
double a,
double b,
);

@ffi.Native<ffi.Int>()
external int log_level;

@ffi.Array.multi([5])
@ffi.Native<ffi.Array<ffi.Int>>()
external ffi.Array<ffi.Int> array;

/// Version of the native C library
@ffi.Native<ffi.Pointer<ffi.Char>>()
external final ffi.Pointer<ffi.Char> library_version;

const addresses = _SymbolAddresses();

class _SymbolAddresses {
const _SymbolAddresses();
ffi.Pointer<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>> get sum =>
ffi.Native.addressOf(self.sum);
simolus3 marked this conversation as resolved.
Show resolved Hide resolved
ffi.Pointer<ffi.Pointer<ffi.Char>> get library_version =>
ffi.Native.addressOf(self.library_version);
}
2 changes: 1 addition & 1 deletion pkgs/ffigen/example/ffinative/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
name: ffinative_example

environment:
sdk: '>=3.2.0 <4.0.0'
sdk: '>=3.3.0-252.0.dev <4.0.0'

dependencies:
ffi: ^2.0.1
Expand Down
15 changes: 2 additions & 13 deletions pkgs/ffigen/lib/src/code_generator/compound.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,6 @@ abstract class Compound extends BindingType {
}
}

List<int> _getArrayDimensionLengths(Type type) {
final array = <int>[];
var startType = type;
while (startType is ConstantArray) {
array.add(startType.length);
startType = startType.child;
}
return array;
}

String _getInlineArrayTypeString(Type type, Writer w) {
if (type is ConstantArray) {
return '${w.ffiLibraryPrefix}.Array<'
Expand Down Expand Up @@ -132,9 +122,8 @@ abstract class Compound extends BindingType {
s.writeAll(m.dartDoc!.split('\n'), '\n$depth/// ');
s.write('\n');
}
if (m.type is ConstantArray) {
s.write('$depth@${w.ffiLibraryPrefix}.Array.multi(');
s.write('${_getArrayDimensionLengths(m.type)})\n');
if (m.type case final ConstantArray arrayType) {
s.writeln(makeArrayAnnotation(w, arrayType));
s.write('${depth}external ${_getInlineArrayTypeString(m.type, w)} ');
s.write('${m.name};\n\n');
} else {
Expand Down
21 changes: 16 additions & 5 deletions pkgs/ffigen/lib/src/code_generator/func.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,15 @@ class Func extends LookUpBinding {
}

if (ffiNativeConfig.enabled) {
final assetString = ffiNativeConfig.assetId != null
? ", assetId: '${ffiNativeConfig.assetId}'"
: '';
final isLeafString = isLeaf ? ', isLeaf:true' : '';
final nativeFuncName = needsWrapper ? funcVarName : enclosingFuncName;
s.write('''
@${w.ffiLibraryPrefix}.Native<$cType>(symbol: '$originalName'$assetString$isLeafString)
${makeNativeAnnotation(
w,
nativeType: cType,
dartName: nativeFuncName,
nativeSymbolName: originalName,
isLeaf: isLeaf,
)}
external $ffiReturnType $nativeFuncName($ffiArgDeclString);

''');
Expand All @@ -164,6 +166,15 @@ $dartReturnType $enclosingFuncName($libArg$dartArgDeclString) => $funcImplCall;

''');
}

if (exposeSymbolAddress) {
// Add to SymbolAddress in writer.
w.symbolAddressWriter.addNativeSymbol(
type:
'${w.ffiLibraryPrefix}.Pointer<${w.ffiLibraryPrefix}.NativeFunction<$cType>>',
name: name,
);
}
} else {
funcPointerName = w.wrapperLevelUniqueNamer.makeUnique('_${name}Ptr');
final isLeafString = isLeaf ? 'isLeaf:true' : '';
Expand Down
76 changes: 54 additions & 22 deletions pkgs/ffigen/lib/src/code_generator/global.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// 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 '../config_provider/config_types.dart';
import 'binding.dart';
import 'binding_string.dart';
import 'compound.dart';
import 'pointer.dart';
import 'type.dart';
import 'utils.dart';
import 'writer.dart';
Expand All @@ -22,6 +24,7 @@ import 'writer.dart';
class Global extends LookUpBinding {
final Type type;
final bool exposeSymbolAddress;
final FfiNativeConfig nativeConfig;
final bool constant;

Global({
Expand All @@ -32,6 +35,7 @@ class Global extends LookUpBinding {
super.dartDoc,
this.exposeSymbolAddress = false,
this.constant = false,
this.nativeConfig = const FfiNativeConfig(enabled: false),
});

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

s.write(
"late final ${w.ffiLibraryPrefix}.Pointer<$cType> $pointerName = ${w.lookupFuncIdentifier}<$cType>('$originalName');\n\n");
final baseTypealiasType = type.typealiasType;
if (baseTypealiasType is Compound) {
if (baseTypealiasType.isOpaque) {
s.write(
'${w.ffiLibraryPrefix}.Pointer<$cType> get $globalVarName => $pointerName;\n\n');
} else {
s.write('$dartType get $globalVarName => $pointerName.ref;\n\n');
if (nativeConfig.enabled) {
if (type case final ConstantArray arr) {
s.writeln(makeArrayAnnotation(w, arr));
}

s
..writeln(makeNativeAnnotation(
w,
nativeType: cType,
dartName: globalVarName,
nativeSymbolName: originalName,
isLeaf: false,
))
..write('external ');
if (constant) {
s.write('final ');
simolus3 marked this conversation as resolved.
Show resolved Hide resolved
}

s.writeln('$dartType $globalVarName;\n');

if (exposeSymbolAddress) {
w.symbolAddressWriter.addNativeSymbol(
type: '${w.ffiLibraryPrefix}.Pointer<$cType>', name: name);
}
} else {
s.write('$dartType get $globalVarName => $pointerName.value;\n\n');
if (!constant) {
s.write(
'set $globalVarName($dartType value) => $pointerName.value = value;\n\n');
final pointerName =
w.wrapperLevelUniqueNamer.makeUnique('_$globalVarName');

s.write(
"late final ${w.ffiLibraryPrefix}.Pointer<$cType> $pointerName = ${w.lookupFuncIdentifier}<$cType>('$originalName');\n\n");
final baseTypealiasType = type.typealiasType;
if (baseTypealiasType is Compound) {
if (baseTypealiasType.isOpaque) {
s.write(
'${w.ffiLibraryPrefix}.Pointer<$cType> get $globalVarName => $pointerName;\n\n');
} else {
s.write('$dartType get $globalVarName => $pointerName.ref;\n\n');
}
} else {
s.write('$dartType get $globalVarName => $pointerName.value;\n\n');
if (!constant) {
s.write(
'set $globalVarName($dartType value) => $pointerName.value = value;\n\n');
}
}
}

if (exposeSymbolAddress) {
// Add to SymbolAddress in writer.
w.symbolAddressWriter.addSymbol(
type: '${w.ffiLibraryPrefix}.Pointer<$cType>',
name: name,
ptrName: pointerName,
);
if (exposeSymbolAddress) {
// Add to SymbolAddress in writer.
w.symbolAddressWriter.addSymbol(
type: '${w.ffiLibraryPrefix}.Pointer<$cType>',
name: name,
ptrName: pointerName,
);
}
}

return BindingString(type: BindingStringType.global, string: s.toString());
Expand Down
1 change: 1 addition & 0 deletions pkgs/ffigen/lib/src/code_generator/imports.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class SelfImportedType extends Type {

final ffiImport = LibraryImport('ffi', 'dart:ffi');
final ffiPkgImport = LibraryImport('pkg_ffi', 'package:ffi/ffi.dart');
final self = LibraryImport('self', '');

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

Expand Down
Loading
Loading