`FfiNative` support (#447)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c91860..0fe4436 100644
--- a/CHANGELOG.md
+++ b/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/README.md b/README.md
index 6442b42..96a88d0 100644
--- a/README.md
+++ b/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/example/ffinative/.gitignore b/example/ffinative/.gitignore
new file mode 100644
index 0000000..1b05164
--- /dev/null
+++ b/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/example/ffinative/README.md b/example/ffinative/README.md
new file mode 100644
index 0000000..c146940
--- /dev/null
+++ b/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/example/ffinative/generated_bindings.dart b/example/ffinative/generated_bindings.dart
new file mode 100644
index 0000000..794f28f
--- /dev/null
+++ b/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/example/ffinative/headers/example.h b/example/ffinative/headers/example.h
new file mode 100644
index 0000000..40c6b9e
--- /dev/null
+++ b/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/example/ffinative/pubspec.yaml b/example/ffinative/pubspec.yaml
new file mode 100644
index 0000000..5ba0423
--- /dev/null
+++ b/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/example/simple/generated_bindings.dart b/example/simple/generated_bindings.dart
index 1612b64..b4c885a 100644
--- a/example/simple/generated_bindings.dart
+++ b/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/example/simple/headers/example.h b/example/simple/headers/example.h
index 0f936ee..40c6b9e 100644
--- a/example/simple/headers/example.h
+++ b/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/lib/src/code_generator/func.dart b/lib/src/code_generator/func.dart
index c10b0c8..4496e71 100644
--- a/lib/src/code_generator/func.dart
+++ b/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/lib/src/code_generator/library.dart b/lib/src/code_generator/library.dart
index a651871..7c7ce47 100644
--- a/lib/src/code_generator/library.dart
+++ b/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/lib/src/code_generator/writer.dart b/lib/src/code_generator/writer.dart
index 77e9e83..1f054fc 100644
--- a/lib/src/code_generator/writer.dart
+++ b/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/lib/src/config_provider/config.dart b/lib/src/config_provider/config.dart
index 56b2df1..1fdb77e 100644
--- a/lib/src/config_provider/config.dart
+++ b/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/lib/src/config_provider/config_types.dart b/lib/src/config_provider/config_types.dart
index 8146917..e3965c0 100644
--- a/lib/src/config_provider/config_types.dart
+++ b/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/lib/src/config_provider/spec_utils.dart b/lib/src/config_provider/spec_utils.dart
index ac154ce..149bd9f 100644
--- a/lib/src/config_provider/spec_utils.dart
+++ b/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/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
index 4e5e150..7eb65a8 100644
--- a/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
+++ b/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/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
index b4c40fc..848f60b 100644
--- a/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
+++ b/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/lib/src/header_parser/sub_parsers/macro_parser.dart b/lib/src/header_parser/sub_parsers/macro_parser.dart
index cdfe078..753a4b5 100644
--- a/lib/src/header_parser/sub_parsers/macro_parser.dart
+++ b/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/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
index 940369a..81c0a77 100644
--- a/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
+++ b/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/lib/src/header_parser/sub_parsers/var_parser.dart b/lib/src/header_parser/sub_parsers/var_parser.dart
index 8376199..a8d46d3 100644
--- a/lib/src/header_parser/sub_parsers/var_parser.dart
+++ b/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/lib/src/strings.dart b/lib/src/strings.dart
index 6995ada..96e3c34 100644
--- a/lib/src/strings.dart
+++ b/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/pubspec.yaml b/pubspec.yaml
index d46f5fd..3de14a4 100644
--- a/pubspec.yaml
+++ b/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/test/example_tests/ffinative_example_test.dart b/test/example_tests/ffinative_example_test.dart
new file mode 100644
index 0000000..67962a0
--- /dev/null
+++ b/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/test/large_integration_tests/_expected_cjson_bindings.dart b/test/large_integration_tests/_expected_cjson_bindings.dart
index ad8b2b5..2abffa6 100644
--- a/test/large_integration_tests/_expected_cjson_bindings.dart
+++ b/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/test/large_integration_tests/_expected_libclang_bindings.dart b/test/large_integration_tests/_expected_libclang_bindings.dart
index d060bd4..f5f332e 100644
--- a/test/large_integration_tests/_expected_libclang_bindings.dart
+++ b/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/test/large_integration_tests/large_test.dart b/test/large_integration_tests/large_test.dart
index 14c54bf..1638951 100644
--- a/test/large_integration_tests/large_test.dart
+++ b/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);