Loading...
Loading...
Guide agents to use `package:ffigen` to automatically generate FFI bindings instead of writing them manually. Use this skill when a task involves writing new FFI bindings, extending C/Objective-C/Swift integrations, or replacing hand-crafted `dart:ffi` setups.
npx skill4agent add dart-lang/skills dart-use-ffigenpackage:ffigenFfiGenerator.hDynamicLibrary.lookup@NativeFfiGeneratortool/ffigen.dartthird_party/src/third_party/Functions.includeSetincludelib/src/third_party/.g.dartsqlite3.g.dartpreambleOutput// Generated by package:ffigen. Do not edit manually.dart analyzerecordUse: (_) => trueFunctionsrecordUseMappingOutput.g.dartlib/src/third_party/lib/src/third_party/sqlite3.record_use_mapping.g.dartpackage:ffigen/ffigen.dartFfiGeneratorFfiGenerator({
Headers headers = const Headers(),
Enums enums = Enums.excludeAll,
Functions functions = Functions.excludeAll,
Globals globals = Globals.excludeAll,
Integers integers = const Integers(),
Macros macros = Macros.excludeAll,
Structs structs = Structs.excludeAll,
Typedefs typedefs = Typedefs.excludeAll,
Unions unions = Unions.excludeAll,
UnnamedEnums unnamedEnums = UnnamedEnums.excludeAll,
ObjectiveC? objectiveC,
required Output output,
}).generate();HeadersentryPointsUriincludebool Function(Uri header)compilerOptionsignoreSourceErrorstrueFunctionsinclude(decl) => {'my_func'}.contains(decl.originalName)Functions.includeSet({'my_func'})isLeaf(decl) => truerecordUsedart-lang/native(_) => trueOutputdartFileUrirecordUseMappingUripreambleformattruepubspec.yamldev_dependenciesffigen^20.1.1dart pub add dev:ffigentool/tool/ffigen.dartPlatform.scriptfinal packageRoot = Platform.script.resolve('../');
final headerFile = packageRoot.resolve('third_party/library.h');
final targetBindings = packageRoot.resolve('lib/src/third_party/bindings.g.dart');tool/ffigen.dartvoid main()FfiGeneratordart run tool/ffigen.dartformat: truedart analyzedart analyzeignore_for_file:preamblecamel_case_typesnon_constant_identifier_namesdart analyzepkgs/code_assets/example/sqlitethird_party/sqlite/third_party/sqlite/sqlite3.h// The author disclaims copyright to this source code. In place of
// a legal notice, here is a blessing:
//
// May you do good and not evil.
// May you find forgiveness for yourself and forgive others.
// May you share freely, never taking more than you give.
#ifndef SQLITE3_H_
#define SQLITE3_H_
const char *sqlite3_libversion(void);
#endif // SQLITE3_H_// lib/src/sqlite3_manual.dart
import 'dart:ffi' as ffi;
import 'package:ffi/ffi.dart';
// Flaw 1: Hardcoded DynamicLibrary lookup blocks integration with modern native asset compilation.
final ffi.DynamicLibrary _dylib = ffi.DynamicLibrary.open('libsqlite3.so');
// Flaw 2: Manual function type matching requires writing redundant dynamic lookup boilerplate and lacks tree-shaking metadata.
typedef _sqlite3_libversion_C = ffi.Pointer<ffi.Char> Function();
typedef _sqlite3_libversion_Dart = ffi.Pointer<ffi.Char> Function();
final _sqlite3_libversion_Dart sqlite3LibVersion = _dylib
.lookup<ffi.NativeFunction<_sqlite3_libversion_C>>('sqlite3_libversion')
.asFunction();tool/ffigen.dart// Copyright (c) 2025, 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 'dart:io';
import 'package:ffigen/ffigen.dart';
void main() {
// Resolve paths dynamically relative to Platform.script
final packageRoot = Platform.script.resolve('../');
final entryHeader = packageRoot.resolve('third_party/sqlite/sqlite3.h');
final bindingsOutput = packageRoot.resolve('lib/src/third_party/sqlite3.g.dart');
final treeShakeMapping = packageRoot.resolve('lib/src/third_party/sqlite3.record_use_mapping.g.dart');
FfiGenerator(
headers: Headers(
entryPoints: [entryHeader],
),
functions: Functions(
include: (decl) => {'sqlite3_libversion'}.contains(decl.originalName),
// Essential for package optimization and tree-shaking
recordUse: (_) => true,
),
output: Output(
dartFile: bindingsOutput,
recordUseMapping: treeShakeMapping,
format: true,
preamble: '''
// The author disclaims copyright to this source code. In place of
// a legal notice, here is a blessing:
//
// May you do good and not evil.
// May you find forgiveness for yourself and forgive others.
// May you share freely, never taking more than you give.
// AUTO-GENERATED FILE - DO NOT MODIFY.
// Generated via ffigen.
// To regenerate: dart run tool/ffigen.dart
// ignore_for_file: type=lint, unused_import, unused_element, deprecated_member_use_from_same_package, experimental_member_use
''',
),
).generate();
print('Successfully generated sqlite3 FFI bindings.');
}dart run tool/ffigen.dartlib/src/third_party/sqlite3.g.dartlib/src/third_party/sqlite3.record_use_mapping.g.dartlib/src/third_party/.g.dartdart analyzeignore_for_filepreamble