[ffigen] `FfiNative` support (#447)
diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md index 5c91860..0fe4436 100644 --- a/pkgs/ffigen/CHANGELOG.md +++ b/pkgs/ffigen/CHANGELOG.md
@@ -1,3 +1,8 @@ +# 6.1.1 + +- _EXPERIMENTAL_ support for `FfiNative`. The API and output + might change at any point. + # 6.1.0 - Added `exclude-all-by-default` config flag, which changes the default behavior
diff --git a/pkgs/ffigen/README.md b/pkgs/ffigen/README.md index 6442b42..96a88d0 100644 --- a/pkgs/ffigen/README.md +++ b/pkgs/ffigen/README.md
@@ -489,6 +489,23 @@ 'dart-type': 'CustomType3' ``` </td> + </tr> + <tr> + <td>ffi-native</td> + <td> + <b>WARNING:</b> FfiNative support is EXPERIMENTAL. The API may change + in a breaking way without notice. + <br><br> + Generate `@FfiNative` bindings instead of bindings using `DynamicLibrary` or `lookup`. + </td> + <td> + +```yaml +ffi-native: + asset: 'myasset' # Optional. +``` + </td> + </tr> <tr> <td>language</td> <td>
diff --git a/pkgs/ffigen/example/ffinative/.gitignore b/pkgs/ffigen/example/ffinative/.gitignore new file mode 100644 index 0000000..1b05164 --- /dev/null +++ b/pkgs/ffigen/example/ffinative/.gitignore
@@ -0,0 +1,11 @@ +# Files and directories created by pub. +.dart_tool/ +.packages +# Remove the following pattern if you wish to check in your lock file. +pubspec.lock + +# Conventional directory for build outputs. +build/ + +# Directory created by dartdoc. +doc/api/
diff --git a/pkgs/ffigen/example/ffinative/README.md b/pkgs/ffigen/example/ffinative/README.md new file mode 100644 index 0000000..c146940 --- /dev/null +++ b/pkgs/ffigen/example/ffinative/README.md
@@ -0,0 +1,10 @@ +# FfiNatives example + +A simple example generating `FfiNative` bindings for a very small header file (`headers/example.h`). + +## Generating bindings +At the root of this example (`example/simple`), run - +``` +dart run ffigen +``` +This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart).
diff --git a/pkgs/ffigen/example/ffinative/generated_bindings.dart b/pkgs/ffigen/example/ffinative/generated_bindings.dart new file mode 100644 index 0000000..794f28f --- /dev/null +++ b/pkgs/ffigen/example/ffinative/generated_bindings.dart
@@ -0,0 +1,41 @@ +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +import 'dart:ffi' as ffi; + +/// Adds 2 integers. +@ffi.FfiNative<ffi.Int Function(ffi.Int, ffi.Int)>('sum') +external int sum( + int a, + int b, +); + +/// Subtracts 2 integers. +@ffi.FfiNative<ffi.Int Function(ffi.Pointer<ffi.Int>, ffi.Int)>('subtract') +external int subtract( + ffi.Pointer<ffi.Int> a, + int b, +); + +/// Multiplies 2 integers, returns pointer to an integer,. +@ffi.FfiNative<ffi.Pointer<ffi.Int> Function(ffi.Int, ffi.Int)>('multiply') +external ffi.Pointer<ffi.Int> multiply( + int a, + int b, +); + +/// Divides 2 integers, returns pointer to a float. +@ffi.FfiNative<ffi.Pointer<ffi.Float> Function(ffi.Int, ffi.Int)>('divide') +external ffi.Pointer<ffi.Float> divide( + int a, + int b, +); + +/// Divides 2 floats, returns a pointer to double. +@ffi.FfiNative< + ffi.Pointer<ffi.Double> Function( + ffi.Pointer<ffi.Float>, ffi.Pointer<ffi.Float>)>('dividePrecision') +external ffi.Pointer<ffi.Double> dividePrecision( + ffi.Pointer<ffi.Float> a, + ffi.Pointer<ffi.Float> b, +);
diff --git a/pkgs/ffigen/example/ffinative/headers/example.h b/pkgs/ffigen/example/ffinative/headers/example.h new file mode 100644 index 0000000..40c6b9e --- /dev/null +++ b/pkgs/ffigen/example/ffinative/headers/example.h
@@ -0,0 +1,18 @@ +// 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. + +/** Adds 2 integers. */ +int sum(int a, int b); + +/** Subtracts 2 integers. */ +int subtract(int *a, int b); + +/** Multiplies 2 integers, returns pointer to an integer,. */ +int *multiply(int a, int b); + +/** Divides 2 integers, returns pointer to a float. */ +float *divide(int a, int b); + +/** Divides 2 floats, returns a pointer to double. */ +double *dividePrecision(float *a, float *b);
diff --git a/pkgs/ffigen/example/ffinative/pubspec.yaml b/pkgs/ffigen/example/ffinative/pubspec.yaml new file mode 100644 index 0000000..5ba0423 --- /dev/null +++ b/pkgs/ffigen/example/ffinative/pubspec.yaml
@@ -0,0 +1,25 @@ +# 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. + +name: ffinative_example + +environment: + sdk: '>=2.17.0 <3.0.0' + +dependencies: + ffi: ^2.0.1 +dev_dependencies: + ffigen: + path: '../../' + lints: ^2.0.0 + +ffigen: + name: NativeLibrary + ffi-native: + # asset: 'assetname' # (optional) + description: Bindings to `headers/example.h`. + output: 'generated_bindings.dart' + headers: + entry-points: + - 'headers/example.h'
diff --git a/pkgs/ffigen/example/simple/generated_bindings.dart b/pkgs/ffigen/example/simple/generated_bindings.dart index 1612b64..b4c885a 100644 --- a/pkgs/ffigen/example/simple/generated_bindings.dart +++ b/pkgs/ffigen/example/simple/generated_bindings.dart
@@ -86,21 +86,21 @@ _dividePtr.asFunction<ffi.Pointer<ffi.Float> Function(int, int)>(); /// Divides 2 floats, returns a pointer to double. - ffi.Pointer<ffi.Double> dividePercision( + ffi.Pointer<ffi.Double> dividePrecision( ffi.Pointer<ffi.Float> a, ffi.Pointer<ffi.Float> b, ) { - return _dividePercision( + return _dividePrecision( a, b, ); } - late final _dividePercisionPtr = _lookup< + late final _dividePrecisionPtr = _lookup< ffi.NativeFunction< ffi.Pointer<ffi.Double> Function(ffi.Pointer<ffi.Float>, - ffi.Pointer<ffi.Float>)>>('dividePercision'); - late final _dividePercision = _dividePercisionPtr.asFunction< + ffi.Pointer<ffi.Float>)>>('dividePrecision'); + late final _dividePrecision = _dividePrecisionPtr.asFunction< ffi.Pointer<ffi.Double> Function( ffi.Pointer<ffi.Float>, ffi.Pointer<ffi.Float>)>(); }
diff --git a/pkgs/ffigen/example/simple/headers/example.h b/pkgs/ffigen/example/simple/headers/example.h index 0f936ee..40c6b9e 100644 --- a/pkgs/ffigen/example/simple/headers/example.h +++ b/pkgs/ffigen/example/simple/headers/example.h
@@ -15,4 +15,4 @@ float *divide(int a, int b); /** Divides 2 floats, returns a pointer to double. */ -double *dividePercision(float *a, float *b); +double *dividePrecision(float *a, float *b);
diff --git a/pkgs/ffigen/lib/src/code_generator/func.dart b/pkgs/ffigen/lib/src/code_generator/func.dart index c10b0c8..4496e71 100644 --- a/pkgs/ffigen/lib/src/code_generator/func.dart +++ b/pkgs/ffigen/lib/src/code_generator/func.dart
@@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:ffigen/src/code_generator.dart'; +import 'package:ffigen/src/config_provider/config_types.dart'; import 'binding_string.dart'; import 'utils.dart'; @@ -10,11 +11,14 @@ /// A binding for C function. /// -/// For a C function - +/// For example, take the following C function. +/// /// ```c /// int sum(int a, int b); /// ``` -/// The Generated dart code is - +/// +/// The generated Dart code for this function (without `FfiNative`) is as follows. +/// /// ```dart /// int sum(int a, int b) { /// return _sum(a, b); @@ -26,11 +30,19 @@ /// /// typedef _dart_sum = int Function(int a, int b); /// ``` +/// +/// When using `FfiNative`, the code is as follows. +/// +/// ```dart +/// @ffi.FfiNative<ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b)>('sum') +/// external int sum(int a, int b); +/// ``` class Func extends LookUpBinding { final FunctionType functionType; final bool exposeSymbolAddress; final bool exposeFunctionTypedefs; final bool isLeaf; + final FfiNativeConfig ffiNativeConfig; late final String funcPointerName; /// Contains typealias for function type if [exposeFunctionTypedefs] is true. @@ -50,6 +62,7 @@ this.exposeFunctionTypedefs = false, this.isLeaf = false, bool isInternal = false, + this.ffiNativeConfig = const FfiNativeConfig(enabled: false), }) : functionType = FunctionType( returnType: returnType, parameters: parameters ?? const [], @@ -97,20 +110,6 @@ for (final p in functionType.parameters) { p.name = paramNamer.makeUnique(p.name); } - // Write enclosing function. - s.write('${functionType.returnType.getDartType(w)} $enclosingFuncName(\n'); - for (final p in functionType.parameters) { - s.write(' ${p.type.getDartType(w)} ${p.name},\n'); - } - s.write(') {\n'); - s.write('return $funcVarName'); - - s.write('(\n'); - for (final p in functionType.parameters) { - s.write(' ${p.name},\n'); - } - s.write(' );\n'); - s.write('}\n'); final cType = exposeFunctionTypedefs ? _exposedCFunctionTypealias!.name @@ -119,21 +118,53 @@ ? _exposedDartFunctionTypealias!.name : functionType.getDartType(w, writeArgumentNames: false); - if (exposeSymbolAddress) { - // Add to SymbolAddress in writer. - w.symbolAddressWriter.addSymbol( - type: - '${w.ffiLibraryPrefix}.Pointer<${w.ffiLibraryPrefix}.NativeFunction<$cType>>', - name: name, - ptrName: funcPointerName, - ); + if (ffiNativeConfig.enabled) { + final assetString = ffiNativeConfig.asset != null + ? ", asset: '${ffiNativeConfig.asset}'" + : ''; + final isLeafString = isLeaf ? ', isLeaf: true' : ''; + s.write( + "@${w.ffiLibraryPrefix}.FfiNative<$cType>('$originalName'$assetString$isLeafString)\n"); + + s.write( + 'external ${functionType.returnType.getDartType(w)} $enclosingFuncName(\n'); + for (final p in functionType.parameters) { + s.write(' ${p.type.getDartType(w)} ${p.name},\n'); + } + s.write(');\n\n'); + } else { + // Write enclosing function. + s.write( + '${functionType.returnType.getDartType(w)} $enclosingFuncName(\n'); + for (final p in functionType.parameters) { + s.write(' ${p.type.getDartType(w)} ${p.name},\n'); + } + s.write(') {\n'); + s.write('return $funcVarName'); + + s.write('(\n'); + for (final p in functionType.parameters) { + s.write(' ${p.name},\n'); + } + s.write(' );\n'); + s.write('}\n'); + + if (exposeSymbolAddress) { + // Add to SymbolAddress in writer. + w.symbolAddressWriter.addSymbol( + type: + '${w.ffiLibraryPrefix}.Pointer<${w.ffiLibraryPrefix}.NativeFunction<$cType>>', + name: name, + ptrName: funcPointerName, + ); + } + // Write function pointer. + s.write( + "late final $funcPointerName = ${w.lookupFuncIdentifier}<${w.ffiLibraryPrefix}.NativeFunction<$cType>>('$originalName');\n"); + final isLeafString = isLeaf ? 'isLeaf:true' : ''; + s.write( + 'late final $funcVarName = $funcPointerName.asFunction<$dartType>($isLeafString);\n\n'); } - // Write function pointer. - s.write( - "late final $funcPointerName = ${w.lookupFuncIdentifier}<${w.ffiLibraryPrefix}.NativeFunction<$cType>>('$originalName');\n"); - final isLeafString = isLeaf ? 'isLeaf:true' : ''; - s.write( - 'late final $funcVarName = $funcPointerName.asFunction<$dartType>($isLeafString);\n\n'); return BindingString(type: BindingStringType.func, string: s.toString()); }
diff --git a/pkgs/ffigen/lib/src/code_generator/library.dart b/pkgs/ffigen/lib/src/code_generator/library.dart index a651871..7c7ce47 100644 --- a/pkgs/ffigen/lib/src/code_generator/library.dart +++ b/pkgs/ffigen/lib/src/code_generator/library.dart
@@ -5,12 +5,12 @@ import 'dart:io'; import 'package:cli_util/cli_util.dart'; +import 'package:ffigen/src/code_generator.dart'; import 'package:ffigen/src/config_provider/config_types.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; -import 'binding.dart'; -import 'imports.dart'; -import 'struct.dart'; + +import '../strings.dart' as strings; import 'utils.dart'; import 'writer.dart'; @@ -46,11 +46,12 @@ _sort(); } - /// Handle any declaration-declaration name conflicts. + /// Handle any declaration-declaration name conflicts and emit warnings. final declConflictHandler = UniqueNamer({}); for (final b in this.bindings) { _warnIfPrivateDeclaration(b); _resolveIfNameConflicts(declConflictHandler, b); + _warnIfExposeSymbolAddressAndFfiNative(b); } // Override pack values according to config. We do this after declaration @@ -64,12 +65,23 @@ } // Seperate bindings which require lookup. - final lookUpBindings = this.bindings.whereType<LookUpBinding>().toList(); + final lookUpBindings = this.bindings.whereType<LookUpBinding>().where((e) { + if (e is Func) { + return !e.ffiNativeConfig.enabled; + } + return true; + }).toList(); + final ffiNativeBindings = this + .bindings + .whereType<Func>() + .where((e) => e.ffiNativeConfig.enabled) + .toList(); final noLookUpBindings = this.bindings.whereType<NoLookUpBinding>().toList(); _writer = Writer( lookUpBindings: lookUpBindings, + ffiNativeBindings: ffiNativeBindings, noLookUpBindings: noLookUpBindings, className: name, classDocComment: description, @@ -100,6 +112,16 @@ } } + /// Logs a warning if generated declaration will be private. + void _warnIfExposeSymbolAddressAndFfiNative(Binding b) { + if (b is Func) { + if (b.exposeSymbolAddress && b.ffiNativeConfig.enabled) { + _logger.warning( + "Ignoring ${strings.symbolAddress} for '${b.name}' because it is generated as FfiNative."); + } + } + } + /// Sort all bindings in alphabetical order. void _sort() { bindings.sort((b1, b2) => b1.name.compareTo(b2.name));
diff --git a/pkgs/ffigen/lib/src/code_generator/writer.dart b/pkgs/ffigen/lib/src/code_generator/writer.dart index 77e9e83..1f054fc 100644 --- a/pkgs/ffigen/lib/src/code_generator/writer.dart +++ b/pkgs/ffigen/lib/src/code_generator/writer.dart
@@ -2,11 +2,9 @@ // 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 'package:ffigen/src/code_generator/imports.dart'; +import 'package:ffigen/src/code_generator.dart'; import 'package:ffigen/src/code_generator/utils.dart'; -import 'binding.dart'; - /// To store generated String bindings. class Writer { final String? header; @@ -14,6 +12,9 @@ /// Holds bindings, which lookup symbols. final List<Binding> lookUpBindings; + /// Holds bindings, which lookup symbols through `FfiNative`. + final List<Binding> ffiNativeBindings; + /// Holds bindings which don't lookup symbols. final List<Binding> noLookUpBindings; @@ -78,6 +79,7 @@ /// already used. This is used to avoid name collisions. Writer({ required this.lookUpBindings, + required this.ffiNativeBindings, required this.noLookUpBindings, required String className, Set<LibraryImport>? additionalImports, @@ -233,6 +235,10 @@ s.write('}\n\n'); } + for (final b in ffiNativeBindings) { + s.write(b.toBindingString(this).string); + } + if (symbolAddressWriter.shouldGenerate) { s.write(symbolAddressWriter.writeClass(this)); }
diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 56b2df1..1fdb77e 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart
@@ -151,6 +151,9 @@ Includer get leafFunctions => _leafFunctions; late Includer _leafFunctions; + FfiNativeConfig get ffiNativeConfig => _ffiNativeConfig; + late FfiNativeConfig _ffiNativeConfig; + Config._(); /// Create config from Yaml map. @@ -505,6 +508,14 @@ extractedResult: (dynamic result) => _leafFunctions = result as Includer, ), + [strings.ffiNative]: Specification<FfiNativeConfig>( + requirement: Requirement.no, + validator: ffiNativeValidator, + extractor: ffiNativeExtractor, + defaultValue: () => FfiNativeConfig(enabled: false), + extractedResult: (dynamic result) => + _ffiNativeConfig = result as FfiNativeConfig, + ) }; } }
diff --git a/pkgs/ffigen/lib/src/config_provider/config_types.dart b/pkgs/ffigen/lib/src/config_provider/config_types.dart index 8146917..e3965c0 100644 --- a/pkgs/ffigen/lib/src/config_provider/config_types.dart +++ b/pkgs/ffigen/lib/src/config_provider/config_types.dart
@@ -402,3 +402,10 @@ return className; } } + +class FfiNativeConfig { + final bool enabled; + final String? asset; + + const FfiNativeConfig({required this.enabled, this.asset}); +}
diff --git a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart index ac154ce..149bd9f 100644 --- a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart +++ b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart
@@ -49,7 +49,8 @@ return false; } } - return last != null; + // The entry for the last key may be null. + return true; } /// Extracts value of nested [key] from [map]. @@ -918,3 +919,32 @@ return _result; } + +FfiNativeConfig ffiNativeExtractor(dynamic yamlConfig) { + final yamlMap = yamlConfig as YamlMap?; + return FfiNativeConfig( + enabled: true, + asset: yamlMap?[strings.ffiNativeAsset] as String?, + ); +} + +bool ffiNativeValidator(List<String> name, dynamic yamlConfig) { + if (!checkType<YamlMap?>(name, yamlConfig)) { + return false; + } + // ignore: prefer_void_to_null + if (checkType<Null>(name, yamlConfig)) { + return true; + } + for (final key in (yamlConfig as YamlMap).keys) { + if (!checkType<String>([...name, key as String], yamlConfig[key])) { + return false; + } + if (key != strings.ffiNativeAsset) { + _logger.severe("'$name -> $key' must be one of the following - ${[ + strings.ffiNativeAsset + ]}"); + } + } + return true; +}
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart index 4e5e150..7eb65a8 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
@@ -10,7 +10,6 @@ import 'package:logging/logging.dart'; import '../clang_bindings/clang_bindings.dart' as clang_types; -import '../data.dart'; import '../includer.dart'; import '../utils.dart';
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart index b4c40fc..848f60b 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
@@ -80,6 +80,7 @@ exposeFunctionTypedefs: config.exposeFunctionTypedefs.shouldInclude(funcName), isLeaf: config.leafFunctions.shouldInclude(funcName), + ffiNativeConfig: config.ffiNativeConfig, ); bindingsIndex.addFuncToSeen(funcUsr, _stack.top.func!); } else if (bindingsIndex.isSeenFunc(funcUsr)) {
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart index cdfe078..753a4b5 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart
@@ -15,7 +15,6 @@ import 'package:path/path.dart' as p; import '../clang_bindings/clang_bindings.dart' as clang_types; -import '../data.dart'; import '../utils.dart'; final _logger = Logger('ffigen.header_parser.macro_parser');
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart index 940369a..81c0a77 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
@@ -10,7 +10,6 @@ import 'package:logging/logging.dart'; import '../clang_bindings/clang_bindings.dart' as clang_types; -import '../data.dart'; import '../utils.dart'; final _logger = Logger('ffigen.header_parser.unnamed_enumdecl_parser');
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart index 8376199..a8d46d3 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart
@@ -8,7 +8,6 @@ import 'package:logging/logging.dart'; import '../clang_bindings/clang_bindings.dart' as clang_types; -import '../data.dart'; import '../utils.dart'; final _logger = Logger('ffigen.header_parser.var_parser'); @@ -34,6 +33,12 @@ return null; } + if (config.ffiNativeConfig.enabled) { + _logger.warning( + "Skipped global variable '$name', not supported in FfiNatives."); + return null; + } + final global = Global( originalName: name, name: config.globals.renameUsingConfig(name),
diff --git a/pkgs/ffigen/lib/src/strings.dart b/pkgs/ffigen/lib/src/strings.dart index 6995ada..96e3c34 100644 --- a/pkgs/ffigen/lib/src/strings.dart +++ b/pkgs/ffigen/lib/src/strings.dart
@@ -232,3 +232,6 @@ /// USR for struct `_Dart_Handle`. const dartHandleUsr = 'c:@S@_Dart_Handle'; + +const ffiNative = 'ffi-native'; +const ffiNativeAsset = 'asset';
diff --git a/pkgs/ffigen/pubspec.yaml b/pkgs/ffigen/pubspec.yaml index d46f5fd..3de14a4 100644 --- a/pkgs/ffigen/pubspec.yaml +++ b/pkgs/ffigen/pubspec.yaml
@@ -3,7 +3,7 @@ # BSD-style license that can be found in the LICENSE file. name: ffigen -version: 6.1.0 +version: 6.1.1 description: Generator for FFI bindings, using LibClang to parse C header files. repository: https://github.com/dart-lang/ffigen
diff --git a/pkgs/ffigen/test/example_tests/ffinative_example_test.dart b/pkgs/ffigen/test/example_tests/ffinative_example_test.dart new file mode 100644 index 0000000..67962a0 --- /dev/null +++ b/pkgs/ffigen/test/example_tests/ffinative_example_test.dart
@@ -0,0 +1,39 @@ +// 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 'package:ffigen/src/config_provider/config.dart'; +import 'package:ffigen/src/header_parser.dart'; +import 'package:ffigen/src/strings.dart' as strings; +import 'package:logging/logging.dart'; +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; + +import '../test_utils.dart'; + +void main() { + group('ffinative_example_test', () { + setUpAll(() { + logWarnings(Level.SEVERE); + }); + + test('ffinative', () { + final config = Config.fromYaml(loadYaml(''' +${strings.name}: NativeLibrary +${strings.ffiNative}: +${strings.description}: Bindings to `headers/example.h`. +${strings.output}: 'generated_bindings.dart' +${strings.headers}: + ${strings.entryPoints}: + - 'example/ffinative/headers/example.h' +''') as YamlMap); + final library = parse(config); + + matchLibraryWithExpected( + library, + ['test', 'debug_generated', 'example_ffinative.dart'], + ['example', 'ffinative', config.output], + ); + }); + }); +}
diff --git a/pkgs/ffigen/test/large_integration_tests/_expected_cjson_bindings.dart b/pkgs/ffigen/test/large_integration_tests/_expected_cjson_bindings.dart index ad8b2b5..2abffa6 100644 --- a/pkgs/ffigen/test/large_integration_tests/_expected_cjson_bindings.dart +++ b/pkgs/ffigen/test/large_integration_tests/_expected_cjson_bindings.dart
@@ -4,7 +4,6 @@ // // Generated by `package:ffigen`. import 'dart:ffi' as ffi; -import 'package:ffi/ffi.dart' as pkg_ffi; /// Bindings to Cjson. class CJson { @@ -1195,7 +1194,7 @@ } late final _cJSON_mallocPtr = - _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(pkg_ffi.Size)>>( + _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size)>>( 'cJSON_malloc'); late final _cJSON_malloc = _cJSON_mallocPtr.asFunction<ffi.Pointer<ffi.Void> Function(int)>(); @@ -1237,8 +1236,8 @@ } class cJSON_Hooks extends ffi.Struct { - external ffi.Pointer< - ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(pkg_ffi.Size)>> + external ffi + .Pointer<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size)>> malloc_fn; external ffi
diff --git a/pkgs/ffigen/test/large_integration_tests/_expected_libclang_bindings.dart b/pkgs/ffigen/test/large_integration_tests/_expected_libclang_bindings.dart index d060bd4..f5f332e 100644 --- a/pkgs/ffigen/test/large_integration_tests/_expected_libclang_bindings.dart +++ b/pkgs/ffigen/test/large_integration_tests/_expected_libclang_bindings.dart
@@ -4,7 +4,6 @@ // // Generated by `package:ffigen`. import 'dart:ffi' as ffi; -import 'package:ffi/ffi.dart' as pkg_ffi; /// Bindings to LibClang. class LibClang { @@ -482,7 +481,7 @@ ffi.Pointer<ffi.Char> clang_getFileContents( CXTranslationUnit tu, CXFile file, - ffi.Pointer<pkg_ffi.Size> size, + ffi.Pointer<ffi.Size> size, ) { return _clang_getFileContents( tu, @@ -494,10 +493,10 @@ late final _clang_getFileContentsPtr = _lookup< ffi.NativeFunction< ffi.Pointer<ffi.Char> Function(CXTranslationUnit, CXFile, - ffi.Pointer<pkg_ffi.Size>)>>('clang_getFileContents'); + ffi.Pointer<ffi.Size>)>>('clang_getFileContents'); late final _clang_getFileContents = _clang_getFileContentsPtr.asFunction< ffi.Pointer<ffi.Char> Function( - CXTranslationUnit, CXFile, ffi.Pointer<pkg_ffi.Size>)>(); + CXTranslationUnit, CXFile, ffi.Pointer<ffi.Size>)>(); /// Returns non-zero if the file1 and file2 point to the same file, or they /// are both NULL.
diff --git a/pkgs/ffigen/test/large_integration_tests/large_test.dart b/pkgs/ffigen/test/large_integration_tests/large_test.dart index 14c54bf..1638951 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_test.dart
@@ -39,10 +39,6 @@ - '**Index.h' ${strings.typeMap}: ${strings.typeMapTypedefs}: - 'size_t': - lib: 'pkg_ffi' - c-type: 'Size' - dart-type: 'int' 'time_t': lib: 'ffi' c-type: 'Int64' @@ -71,12 +67,6 @@ - third_party/cjson_library/cJSON.h ${strings.includeDirectives}: - '**cJSON.h' -${strings.typeMap}: - ${strings.typeMapTypedefs}: - 'size_t': - lib: 'pkg_ffi' - c-type: 'Size' - dart-type: 'int' ${strings.preamble}: | // ignore_for_file: camel_case_types, non_constant_identifier_names ''') as YamlMap);