[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-flutter-dart-use-ffigen":3,"mdc--q1jac4-key":29,"related-repo-flutter-dart-use-ffigen":1966,"related-org-flutter-dart-use-ffigen":2044},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":19,"repoUrl":20,"updatedAt":21,"license":22,"forks":23,"topics":24,"repo":25,"sourceUrl":27,"mdContent":28},"dart-use-ffigen","generate FFI bindings with ffigen","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\u002FObjective-C\u002FSwift integrations, or replacing hand-crafted `dart:ffi` setups.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"flutter","Flutter (Google)","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fflutter.png",[12,16],{"name":13,"slug":14,"type":15},"Engineering","engineering","tag",{"name":17,"slug":18,"type":15},"Dart","dart",2664,"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins","2026-07-15T05:22:17.592351",null,155,[],{"repoUrl":20,"stars":19,"forks":23,"topics":26,"description":22},[],"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins\u002Ftree\u002FHEAD\u002Fskills\u002Fdart-use-ffigen","---\nname: dart-use-ffigen\ndescription: 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\u002FObjective-C\u002FSwift integrations, or replacing hand-crafted `dart:ffi` setups.\nmetadata:\n  model: models\u002Fgemini-3.1-pro-preview\n  last_modified: Thu, 28 May 2026 07:21:07 GMT\n---\n# Generating FFI Bindings using package:ffigen\n\n## Contents\n- [Introduction](#introduction)\n- [Constraints](#constraints)\n- [FFIgen Overview](#ffigen-overview)\n- [Step-by-Step Workflow](#step-by-step-workflow)\n- [Concrete Example: Binding a C Library](#concrete-example-binding-a-c-library)\n- [Verification Checklist](#verification-checklist)\n\n## Introduction\n\nAutomate and standardize the generation of FFI bindings using `package:ffigen` (`FfiGenerator`). Writing FFI bindings by hand is error-prone, brittle, and highly discouraged.\n\n## Constraints\n\n*   **No Hand-Written FFI Bindings**: If native headers (`.h` files) exist or are generated by a build step, never write manual `DynamicLibrary.lookup`, `@Native` external functions, or raw struct classes. Always use `FfiGenerator` to generate them.\n*   **Generator Location**: The generator script should be located at `tool\u002Fffigen.dart` within the target package root.\n*   **Header Location**: If the native header files are third-party, they should be located in `third_party\u002F` within the target package (otherwise placing them in a `src\u002F` directory at the package root is also acceptable). If the headers are not in one of these standard locations, notify the user that it would be cleaner to move the header files to the standard location (e.g., `third_party\u002F`).\n*   **Targeted Inclusion Filters**: Avoid importing an entire native library unless specifically needed. Always apply precise inclusion lists using positive matches to minimize the size and cognitive load of the generated code (e.g., using `Functions.includeSet` or filtering matches in `include` closures).\n*   **Output Setup**: If the generated FFI bindings interface with a third-party library (or reference third-party headers), the generated files must always be placed under `lib\u002Fsrc\u002Fthird_party\u002F`. The primary generated FFI bindings file must strictly use the `.g.dart` extension (e.g. `sqlite3.g.dart`).\n*   **Preamble & License Headers**: Always supply a premium `preamble` in the `Output` class to specify the license. This must match the native third-party library's license, explicitly include the copyright header of the target native header file, and contain an automatic generation warning (e.g. `\u002F\u002F Generated by package:ffigen. Do not edit manually.`).\n*   **No Unnecessary Commits of Stale Bindings**: Ensure you run the generator script and check if the generated files have changed *before* finishing your task. Always verify the package by running `dart analyze`.\n*   **Record Usage and Tree Shaking**: If the package is integrated into standard runtime execution or compiles native assets via native hooks:\n    *   Enable recorded usage on all functions by setting `recordUse: (_) => true` under `Functions`.\n    *   Specify the `recordUseMapping` target in `Output` (which must strictly be a `.g.dart` file under `lib\u002Fsrc\u002Fthird_party\u002F`, e.g. `lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.record_use_mapping.g.dart`) to register bindings for symbol tree shaking.\n\n## FFIgen Overview\n\nTo construct the programmatic generator, use the core configuration objects imported from `package:ffigen\u002Fffigen.dart`:\n\n### 1. `FfiGenerator`\nThe parent class that orchestrates the configuration, parsing, and code generation.\n```dart\nFfiGenerator({\n  Headers headers = const Headers(),\n  Enums enums = Enums.excludeAll,\n  Functions functions = Functions.excludeAll,\n  Globals globals = Globals.excludeAll,\n  Integers integers = const Integers(),\n  Macros macros = Macros.excludeAll,\n  Structs structs = Structs.excludeAll,\n  Typedefs typedefs = Typedefs.excludeAll,\n  Unions unions = Unions.excludeAll,\n  UnnamedEnums unnamedEnums = UnnamedEnums.excludeAll,\n  ObjectiveC? objectiveC,\n  required Output output,\n}).generate();\n```\n\n### 2. `Headers`\nConfigures Clang header parsing targets and compiler flags.\n*   `entryPoints`: A list of target header `Uri` inputs.\n*   `include`: A filter function `bool Function(Uri header)` that handles transitive header imports.\n*   `compilerOptions`: Custom preprocessor\u002Finclude compiler flags to pass directly to libclang.\n*   `ignoreSourceErrors`: Set to `true` to silence errors occurring inside third-party headers during parsing.\n\n### 3. `Functions`\nSpecifies which native C\u002FC++ functions to expose in Dart.\n*   `include`: A matcher function (e.g. `(decl) => {'my_func'}.contains(decl.originalName)` or `Functions.includeSet({'my_func'})`).\n*   `isLeaf`: Declares functions as leaf functions (`(decl) => true`) if they do not call back into Dart or block thread execution.\n*   `recordUse`: Enables metadata generation for native asset tree shaking (essential in `dart-lang\u002Fnative`). Set to `(_) => true`.\n\n### 4. `Output`\nConfigures target generated files.\n*   `dartFile`: Target `Uri` where the primary FFI bindings will be written.\n*   `recordUseMapping`: Target `Uri` for recorded usage metadata maps (crucial for linking-time tree shaking).\n*   `preamble`: Text inserted at the top of the generated file (licensing, annotations).\n*   `format`: Set to `true` to run the Dart formatter automatically.\n\n## Step-by-Step Workflow\n\n### Step 1: Check\u002FAdd Dependencies\nOpen the package's `pubspec.yaml` and verify the `dev_dependencies` contains `ffigen`. Use the Dart MCP server or look up the latest version on [pub.dev](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fffigen) (e.g., `^20.1.1`).\n\nYou can add it automatically using the CLI:\n```bash\ndart pub add dev:ffigen\n```\n\n### Step 2: Formulate Paths Dynamically\nCreate a programmatic generator script under the package's `tool\u002F` directory (e.g., `tool\u002Fffigen.dart`).\nResolve paths relative to `Platform.script` to make sure it runs successfully from any working directory:\n\n```dart\nfinal packageRoot = Platform.script.resolve('..\u002F');\nfinal headerFile = packageRoot.resolve('third_party\u002Flibrary.h');\nfinal targetBindings = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fbindings.g.dart');\n```\n\n### Step 3: Write the Script (`tool\u002Fffigen.dart`)\nDefine `void main()` and run `FfiGenerator` with dynamic options (see complete example below).\n\n### Step 4: Run Code Generation\nExecute the script from the terminal inside the target package folder:\n```bash\ndart run tool\u002Fffigen.dart\n```\n\n### Step 5: Static Analysis\nVerify that the generated bindings are correct and resolve any analysis issues. FFIgen automatically runs the Dart formatter on the output file (via `format: true` configuration), so manual formatting is not required.\n\n1.  Run the static analyzer inside the target package:\n    ```bash\n    dart analyze\n    ```\n2.  **Addressing Warnings\u002FLints**: If `dart analyze` reports style or lint warnings inside the generated file, append the corresponding warning codes to the `ignore_for_file:` list in your generator script's `preamble` configuration (e.g., adding `camel_case_types`, `non_constant_identifier_names`, etc.). Do not modify the package's global rules.\n3.  **Addressing Compilation Errors**: If `dart analyze` reports actual compiler or analysis errors (not warnings) inside the generated file, do not attempt to edit the generated file manually. Report these error details directly to the user so they can file an issue on the repository at [github.com\u002Fdart-lang\u002Fnative](https:\u002F\u002Fgithub.com\u002Fdart-lang\u002Fnative).\n\n\n## Concrete Example: Binding a C Library\n\nLet's assume we are working with the SQLite package under `pkgs\u002Fcode_assets\u002Fexample\u002Fsqlite`, which embeds SQLite C library sources inside `third_party\u002Fsqlite\u002F` and accesses it via FFI.\n\n### The C Header File (`third_party\u002Fsqlite\u002Fsqlite3.h`)\n```c\n\u002F\u002F The author disclaims copyright to this source code.\n\n#ifndef SQLITE3_H_\n#define SQLITE3_H_\n\nconst char *sqlite3_libversion(void);\n\n#endif \u002F\u002F SQLITE3_H_\n```\n\n### BEFORE: Manual FFI Binding (The Anti-Pattern)\nA developer might attempt to handcraft this integration. It is fragile, blocks tree-shaking metadata, and is highly prone to ABI and structural mapping issues:\n\n```dart\n\u002F\u002F lib\u002Fsrc\u002Fsqlite3_manual.dart\nimport 'dart:ffi' as ffi;\nimport 'package:ffi\u002Fffi.dart';\n\n\u002F\u002F Flaw 1: Hardcoded DynamicLibrary lookup blocks integration with modern native asset compilation.\nfinal ffi.DynamicLibrary _dylib = ffi.DynamicLibrary.open('libsqlite3.so');\n\n\u002F\u002F Flaw 2: Manual function type matching requires writing redundant dynamic lookup boilerplate and lacks tree-shaking metadata.\ntypedef _sqlite3_libversion_C = ffi.Pointer\u003Cffi.Char> Function();\ntypedef _sqlite3_libversion_Dart = ffi.Pointer\u003Cffi.Char> Function();\n\nfinal _sqlite3_libversion_Dart sqlite3LibVersion = _dylib\n    .lookup\u003Cffi.NativeFunction\u003C_sqlite3_libversion_C>>('sqlite3_libversion')\n    .asFunction();\n```\n\n### AFTER: Generating via FFIgen (The Correct Pattern)\n\nCreate a programmatic script at `tool\u002Fffigen.dart`:\n\n```dart\n\u002F\u002F Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file\n\u002F\u002F for details. All rights reserved. Use of this source code is governed by a\n\u002F\u002F BSD-style license that can be found in the LICENSE file.\n\nimport 'dart:io';\nimport 'package:ffigen\u002Fffigen.dart';\n\nvoid main() {\n  \u002F\u002F Resolve paths dynamically relative to Platform.script\n  final packageRoot = Platform.script.resolve('..\u002F');\n  final entryHeader = packageRoot.resolve('third_party\u002Fsqlite\u002Fsqlite3.h');\n  final bindingsOutput = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.g.dart');\n  final treeShakeMapping = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.record_use_mapping.g.dart');\n\n  FfiGenerator(\n    headers: Headers(\n      entryPoints: [entryHeader],\n    ),\n    functions: Functions(\n      include: (decl) => {'sqlite3_libversion'}.contains(decl.originalName),\n      \u002F\u002F Essential for package optimization and tree-shaking\n      recordUse: (_) => true,\n    ),\n    output: Output(\n      dartFile: bindingsOutput,\n      recordUseMapping: treeShakeMapping,\n      format: true,\n      preamble: '''\n\n\u002F\u002F AUTO-GENERATED FILE - DO NOT MODIFY.\n\u002F\u002F Generated via ffigen.\n\u002F\u002F To regenerate: dart run tool\u002Fffigen.dart\n\n\u002F\u002F ignore_for_file: type=lint, unused_import, unused_element, deprecated_member_use_from_same_package, experimental_member_use\n''',\n    ),\n  ).generate();\n\n  print('Successfully generated sqlite3 FFI bindings.');\n}\n```\n\n### Running the Generator script\nRun this in the package root directory:\n```bash\ndart run tool\u002Fffigen.dart\n```\n\nThis will automatically create:\n1.  `lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.g.dart`\n2.  `lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.record_use_mapping.g.dart`\n\n## Verification Checklist\n\nAlways perform the following verification before completing a binding generation task:\n\n1.  **Correct Setup**: Verify the target generated files are inside `lib\u002Fsrc\u002Fthird_party\u002F` (required for third-party licensed code) and the primary FFI bindings file strictly uses the `.g.dart` extension.\n2.  **Static Analysis**: Run `dart analyze` and ensure there are zero compiler\u002Fanalyzer errors or warnings in the package.\n    *   If static warnings are reported in the generated bindings, suppress them by adding `ignore_for_file` rules to the generator's `preamble` configuration (do not modify global package rules).\n    *   If actual compiler or analyzer errors are reported in the generated bindings, do not edit the generated file manually. Report the details to the user and direct them to file an issue at [github.com\u002Fdart-lang\u002Fnative](https:\u002F\u002Fgithub.com\u002Fdart-lang\u002Fnative).\n",{"data":30,"body":34},{"name":4,"description":6,"metadata":31},{"model":32,"last_modified":33},"models\u002Fgemini-3.1-pro-preview","Thu, 28 May 2026 07:21:07 GMT",{"type":35,"children":36},"root",[37,46,53,113,118,141,146,435,440,453,465,470,608,620,625,695,706,711,784,795,800,864,869,875,921,926,959,965,993,1024,1037,1057,1063,1068,1092,1098,1111,1210,1215,1236,1249,1326,1332,1337,1453,1459,1470,1815,1821,1826,1847,1852,1872,1877,1882,1960],{"type":38,"tag":39,"props":40,"children":42},"element","h1",{"id":41},"generating-ffi-bindings-using-packageffigen",[43],{"type":44,"value":45},"text","Generating FFI Bindings using package:ffigen",{"type":38,"tag":47,"props":48,"children":50},"h2",{"id":49},"contents",[51],{"type":44,"value":52},"Contents",{"type":38,"tag":54,"props":55,"children":56},"ul",{},[57,68,77,86,95,104],{"type":38,"tag":58,"props":59,"children":60},"li",{},[61],{"type":38,"tag":62,"props":63,"children":65},"a",{"href":64},"#introduction",[66],{"type":44,"value":67},"Introduction",{"type":38,"tag":58,"props":69,"children":70},{},[71],{"type":38,"tag":62,"props":72,"children":74},{"href":73},"#constraints",[75],{"type":44,"value":76},"Constraints",{"type":38,"tag":58,"props":78,"children":79},{},[80],{"type":38,"tag":62,"props":81,"children":83},{"href":82},"#ffigen-overview",[84],{"type":44,"value":85},"FFIgen Overview",{"type":38,"tag":58,"props":87,"children":88},{},[89],{"type":38,"tag":62,"props":90,"children":92},{"href":91},"#step-by-step-workflow",[93],{"type":44,"value":94},"Step-by-Step Workflow",{"type":38,"tag":58,"props":96,"children":97},{},[98],{"type":38,"tag":62,"props":99,"children":101},{"href":100},"#concrete-example-binding-a-c-library",[102],{"type":44,"value":103},"Concrete Example: Binding a C Library",{"type":38,"tag":58,"props":105,"children":106},{},[107],{"type":38,"tag":62,"props":108,"children":110},{"href":109},"#verification-checklist",[111],{"type":44,"value":112},"Verification Checklist",{"type":38,"tag":47,"props":114,"children":116},{"id":115},"introduction",[117],{"type":44,"value":67},{"type":38,"tag":119,"props":120,"children":121},"p",{},[122,124,131,133,139],{"type":44,"value":123},"Automate and standardize the generation of FFI bindings using ",{"type":38,"tag":125,"props":126,"children":128},"code",{"className":127},[],[129],{"type":44,"value":130},"package:ffigen",{"type":44,"value":132}," (",{"type":38,"tag":125,"props":134,"children":136},{"className":135},[],[137],{"type":44,"value":138},"FfiGenerator",{"type":44,"value":140},"). Writing FFI bindings by hand is error-prone, brittle, and highly discouraged.",{"type":38,"tag":47,"props":142,"children":144},{"id":143},"constraints",[145],{"type":44,"value":76},{"type":38,"tag":54,"props":147,"children":148},{},[149,191,209,242,268,301,334,360],{"type":38,"tag":58,"props":150,"children":151},{},[152,158,160,166,168,174,176,182,184,189],{"type":38,"tag":153,"props":154,"children":155},"strong",{},[156],{"type":44,"value":157},"No Hand-Written FFI Bindings",{"type":44,"value":159},": If native headers (",{"type":38,"tag":125,"props":161,"children":163},{"className":162},[],[164],{"type":44,"value":165},".h",{"type":44,"value":167}," files) exist or are generated by a build step, never write manual ",{"type":38,"tag":125,"props":169,"children":171},{"className":170},[],[172],{"type":44,"value":173},"DynamicLibrary.lookup",{"type":44,"value":175},", ",{"type":38,"tag":125,"props":177,"children":179},{"className":178},[],[180],{"type":44,"value":181},"@Native",{"type":44,"value":183}," external functions, or raw struct classes. Always use ",{"type":38,"tag":125,"props":185,"children":187},{"className":186},[],[188],{"type":44,"value":138},{"type":44,"value":190}," to generate them.",{"type":38,"tag":58,"props":192,"children":193},{},[194,199,201,207],{"type":38,"tag":153,"props":195,"children":196},{},[197],{"type":44,"value":198},"Generator Location",{"type":44,"value":200},": The generator script should be located at ",{"type":38,"tag":125,"props":202,"children":204},{"className":203},[],[205],{"type":44,"value":206},"tool\u002Fffigen.dart",{"type":44,"value":208}," within the target package root.",{"type":38,"tag":58,"props":210,"children":211},{},[212,217,219,225,227,233,235,240],{"type":38,"tag":153,"props":213,"children":214},{},[215],{"type":44,"value":216},"Header Location",{"type":44,"value":218},": If the native header files are third-party, they should be located in ",{"type":38,"tag":125,"props":220,"children":222},{"className":221},[],[223],{"type":44,"value":224},"third_party\u002F",{"type":44,"value":226}," within the target package (otherwise placing them in a ",{"type":38,"tag":125,"props":228,"children":230},{"className":229},[],[231],{"type":44,"value":232},"src\u002F",{"type":44,"value":234}," directory at the package root is also acceptable). If the headers are not in one of these standard locations, notify the user that it would be cleaner to move the header files to the standard location (e.g., ",{"type":38,"tag":125,"props":236,"children":238},{"className":237},[],[239],{"type":44,"value":224},{"type":44,"value":241},").",{"type":38,"tag":58,"props":243,"children":244},{},[245,250,252,258,260,266],{"type":38,"tag":153,"props":246,"children":247},{},[248],{"type":44,"value":249},"Targeted Inclusion Filters",{"type":44,"value":251},": Avoid importing an entire native library unless specifically needed. Always apply precise inclusion lists using positive matches to minimize the size and cognitive load of the generated code (e.g., using ",{"type":38,"tag":125,"props":253,"children":255},{"className":254},[],[256],{"type":44,"value":257},"Functions.includeSet",{"type":44,"value":259}," or filtering matches in ",{"type":38,"tag":125,"props":261,"children":263},{"className":262},[],[264],{"type":44,"value":265},"include",{"type":44,"value":267}," closures).",{"type":38,"tag":58,"props":269,"children":270},{},[271,276,278,284,286,292,294,300],{"type":38,"tag":153,"props":272,"children":273},{},[274],{"type":44,"value":275},"Output Setup",{"type":44,"value":277},": If the generated FFI bindings interface with a third-party library (or reference third-party headers), the generated files must always be placed under ",{"type":38,"tag":125,"props":279,"children":281},{"className":280},[],[282],{"type":44,"value":283},"lib\u002Fsrc\u002Fthird_party\u002F",{"type":44,"value":285},". The primary generated FFI bindings file must strictly use the ",{"type":38,"tag":125,"props":287,"children":289},{"className":288},[],[290],{"type":44,"value":291},".g.dart",{"type":44,"value":293}," extension (e.g. ",{"type":38,"tag":125,"props":295,"children":297},{"className":296},[],[298],{"type":44,"value":299},"sqlite3.g.dart",{"type":44,"value":241},{"type":38,"tag":58,"props":302,"children":303},{},[304,309,311,317,319,325,327,333],{"type":38,"tag":153,"props":305,"children":306},{},[307],{"type":44,"value":308},"Preamble & License Headers",{"type":44,"value":310},": Always supply a premium ",{"type":38,"tag":125,"props":312,"children":314},{"className":313},[],[315],{"type":44,"value":316},"preamble",{"type":44,"value":318}," in the ",{"type":38,"tag":125,"props":320,"children":322},{"className":321},[],[323],{"type":44,"value":324},"Output",{"type":44,"value":326}," class to specify the license. This must match the native third-party library's license, explicitly include the copyright header of the target native header file, and contain an automatic generation warning (e.g. ",{"type":38,"tag":125,"props":328,"children":330},{"className":329},[],[331],{"type":44,"value":332},"\u002F\u002F Generated by package:ffigen. Do not edit manually.",{"type":44,"value":241},{"type":38,"tag":58,"props":335,"children":336},{},[337,342,344,350,352,358],{"type":38,"tag":153,"props":338,"children":339},{},[340],{"type":44,"value":341},"No Unnecessary Commits of Stale Bindings",{"type":44,"value":343},": Ensure you run the generator script and check if the generated files have changed ",{"type":38,"tag":345,"props":346,"children":347},"em",{},[348],{"type":44,"value":349},"before",{"type":44,"value":351}," finishing your task. Always verify the package by running ",{"type":38,"tag":125,"props":353,"children":355},{"className":354},[],[356],{"type":44,"value":357},"dart analyze",{"type":44,"value":359},".",{"type":38,"tag":58,"props":361,"children":362},{},[363,368,370],{"type":38,"tag":153,"props":364,"children":365},{},[366],{"type":44,"value":367},"Record Usage and Tree Shaking",{"type":44,"value":369},": If the package is integrated into standard runtime execution or compiles native assets via native hooks:\n",{"type":38,"tag":54,"props":371,"children":372},{},[373,393],{"type":38,"tag":58,"props":374,"children":375},{},[376,378,384,386,392],{"type":44,"value":377},"Enable recorded usage on all functions by setting ",{"type":38,"tag":125,"props":379,"children":381},{"className":380},[],[382],{"type":44,"value":383},"recordUse: (_) => true",{"type":44,"value":385}," under ",{"type":38,"tag":125,"props":387,"children":389},{"className":388},[],[390],{"type":44,"value":391},"Functions",{"type":44,"value":359},{"type":38,"tag":58,"props":394,"children":395},{},[396,398,404,406,411,413,418,420,425,427,433],{"type":44,"value":397},"Specify the ",{"type":38,"tag":125,"props":399,"children":401},{"className":400},[],[402],{"type":44,"value":403},"recordUseMapping",{"type":44,"value":405}," target in ",{"type":38,"tag":125,"props":407,"children":409},{"className":408},[],[410],{"type":44,"value":324},{"type":44,"value":412}," (which must strictly be a ",{"type":38,"tag":125,"props":414,"children":416},{"className":415},[],[417],{"type":44,"value":291},{"type":44,"value":419}," file under ",{"type":38,"tag":125,"props":421,"children":423},{"className":422},[],[424],{"type":44,"value":283},{"type":44,"value":426},", e.g. ",{"type":38,"tag":125,"props":428,"children":430},{"className":429},[],[431],{"type":44,"value":432},"lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.record_use_mapping.g.dart",{"type":44,"value":434},") to register bindings for symbol tree shaking.",{"type":38,"tag":47,"props":436,"children":438},{"id":437},"ffigen-overview",[439],{"type":44,"value":85},{"type":38,"tag":119,"props":441,"children":442},{},[443,445,451],{"type":44,"value":444},"To construct the programmatic generator, use the core configuration objects imported from ",{"type":38,"tag":125,"props":446,"children":448},{"className":447},[],[449],{"type":44,"value":450},"package:ffigen\u002Fffigen.dart",{"type":44,"value":452},":",{"type":38,"tag":454,"props":455,"children":457},"h3",{"id":456},"_1-ffigenerator",[458,460],{"type":44,"value":459},"1. ",{"type":38,"tag":125,"props":461,"children":463},{"className":462},[],[464],{"type":44,"value":138},{"type":38,"tag":119,"props":466,"children":467},{},[468],{"type":44,"value":469},"The parent class that orchestrates the configuration, parsing, and code generation.",{"type":38,"tag":471,"props":472,"children":476},"pre",{"className":473,"code":474,"language":18,"meta":475,"style":475},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","FfiGenerator({\n  Headers headers = const Headers(),\n  Enums enums = Enums.excludeAll,\n  Functions functions = Functions.excludeAll,\n  Globals globals = Globals.excludeAll,\n  Integers integers = const Integers(),\n  Macros macros = Macros.excludeAll,\n  Structs structs = Structs.excludeAll,\n  Typedefs typedefs = Typedefs.excludeAll,\n  Unions unions = Unions.excludeAll,\n  UnnamedEnums unnamedEnums = UnnamedEnums.excludeAll,\n  ObjectiveC? objectiveC,\n  required Output output,\n}).generate();\n","",[477],{"type":38,"tag":125,"props":478,"children":479},{"__ignoreMap":475},[480,491,500,509,518,527,536,545,554,563,572,581,590,599],{"type":38,"tag":481,"props":482,"children":485},"span",{"class":483,"line":484},"line",1,[486],{"type":38,"tag":481,"props":487,"children":488},{},[489],{"type":44,"value":490},"FfiGenerator({\n",{"type":38,"tag":481,"props":492,"children":494},{"class":483,"line":493},2,[495],{"type":38,"tag":481,"props":496,"children":497},{},[498],{"type":44,"value":499},"  Headers headers = const Headers(),\n",{"type":38,"tag":481,"props":501,"children":503},{"class":483,"line":502},3,[504],{"type":38,"tag":481,"props":505,"children":506},{},[507],{"type":44,"value":508},"  Enums enums = Enums.excludeAll,\n",{"type":38,"tag":481,"props":510,"children":512},{"class":483,"line":511},4,[513],{"type":38,"tag":481,"props":514,"children":515},{},[516],{"type":44,"value":517},"  Functions functions = Functions.excludeAll,\n",{"type":38,"tag":481,"props":519,"children":521},{"class":483,"line":520},5,[522],{"type":38,"tag":481,"props":523,"children":524},{},[525],{"type":44,"value":526},"  Globals globals = Globals.excludeAll,\n",{"type":38,"tag":481,"props":528,"children":530},{"class":483,"line":529},6,[531],{"type":38,"tag":481,"props":532,"children":533},{},[534],{"type":44,"value":535},"  Integers integers = const Integers(),\n",{"type":38,"tag":481,"props":537,"children":539},{"class":483,"line":538},7,[540],{"type":38,"tag":481,"props":541,"children":542},{},[543],{"type":44,"value":544},"  Macros macros = Macros.excludeAll,\n",{"type":38,"tag":481,"props":546,"children":548},{"class":483,"line":547},8,[549],{"type":38,"tag":481,"props":550,"children":551},{},[552],{"type":44,"value":553},"  Structs structs = Structs.excludeAll,\n",{"type":38,"tag":481,"props":555,"children":557},{"class":483,"line":556},9,[558],{"type":38,"tag":481,"props":559,"children":560},{},[561],{"type":44,"value":562},"  Typedefs typedefs = Typedefs.excludeAll,\n",{"type":38,"tag":481,"props":564,"children":566},{"class":483,"line":565},10,[567],{"type":38,"tag":481,"props":568,"children":569},{},[570],{"type":44,"value":571},"  Unions unions = Unions.excludeAll,\n",{"type":38,"tag":481,"props":573,"children":575},{"class":483,"line":574},11,[576],{"type":38,"tag":481,"props":577,"children":578},{},[579],{"type":44,"value":580},"  UnnamedEnums unnamedEnums = UnnamedEnums.excludeAll,\n",{"type":38,"tag":481,"props":582,"children":584},{"class":483,"line":583},12,[585],{"type":38,"tag":481,"props":586,"children":587},{},[588],{"type":44,"value":589},"  ObjectiveC? objectiveC,\n",{"type":38,"tag":481,"props":591,"children":593},{"class":483,"line":592},13,[594],{"type":38,"tag":481,"props":595,"children":596},{},[597],{"type":44,"value":598},"  required Output output,\n",{"type":38,"tag":481,"props":600,"children":602},{"class":483,"line":601},14,[603],{"type":38,"tag":481,"props":604,"children":605},{},[606],{"type":44,"value":607},"}).generate();\n",{"type":38,"tag":454,"props":609,"children":611},{"id":610},"_2-headers",[612,614],{"type":44,"value":613},"2. ",{"type":38,"tag":125,"props":615,"children":617},{"className":616},[],[618],{"type":44,"value":619},"Headers",{"type":38,"tag":119,"props":621,"children":622},{},[623],{"type":44,"value":624},"Configures Clang header parsing targets and compiler flags.",{"type":38,"tag":54,"props":626,"children":627},{},[628,647,665,676],{"type":38,"tag":58,"props":629,"children":630},{},[631,637,639,645],{"type":38,"tag":125,"props":632,"children":634},{"className":633},[],[635],{"type":44,"value":636},"entryPoints",{"type":44,"value":638},": A list of target header ",{"type":38,"tag":125,"props":640,"children":642},{"className":641},[],[643],{"type":44,"value":644},"Uri",{"type":44,"value":646}," inputs.",{"type":38,"tag":58,"props":648,"children":649},{},[650,655,657,663],{"type":38,"tag":125,"props":651,"children":653},{"className":652},[],[654],{"type":44,"value":265},{"type":44,"value":656},": A filter function ",{"type":38,"tag":125,"props":658,"children":660},{"className":659},[],[661],{"type":44,"value":662},"bool Function(Uri header)",{"type":44,"value":664}," that handles transitive header imports.",{"type":38,"tag":58,"props":666,"children":667},{},[668,674],{"type":38,"tag":125,"props":669,"children":671},{"className":670},[],[672],{"type":44,"value":673},"compilerOptions",{"type":44,"value":675},": Custom preprocessor\u002Finclude compiler flags to pass directly to libclang.",{"type":38,"tag":58,"props":677,"children":678},{},[679,685,687,693],{"type":38,"tag":125,"props":680,"children":682},{"className":681},[],[683],{"type":44,"value":684},"ignoreSourceErrors",{"type":44,"value":686},": Set to ",{"type":38,"tag":125,"props":688,"children":690},{"className":689},[],[691],{"type":44,"value":692},"true",{"type":44,"value":694}," to silence errors occurring inside third-party headers during parsing.",{"type":38,"tag":454,"props":696,"children":698},{"id":697},"_3-functions",[699,701],{"type":44,"value":700},"3. ",{"type":38,"tag":125,"props":702,"children":704},{"className":703},[],[705],{"type":44,"value":391},{"type":38,"tag":119,"props":707,"children":708},{},[709],{"type":44,"value":710},"Specifies which native C\u002FC++ functions to expose in Dart.",{"type":38,"tag":54,"props":712,"children":713},{},[714,739,758],{"type":38,"tag":58,"props":715,"children":716},{},[717,722,724,730,732,738],{"type":38,"tag":125,"props":718,"children":720},{"className":719},[],[721],{"type":44,"value":265},{"type":44,"value":723},": A matcher function (e.g. ",{"type":38,"tag":125,"props":725,"children":727},{"className":726},[],[728],{"type":44,"value":729},"(decl) => {'my_func'}.contains(decl.originalName)",{"type":44,"value":731}," or ",{"type":38,"tag":125,"props":733,"children":735},{"className":734},[],[736],{"type":44,"value":737},"Functions.includeSet({'my_func'})",{"type":44,"value":241},{"type":38,"tag":58,"props":740,"children":741},{},[742,748,750,756],{"type":38,"tag":125,"props":743,"children":745},{"className":744},[],[746],{"type":44,"value":747},"isLeaf",{"type":44,"value":749},": Declares functions as leaf functions (",{"type":38,"tag":125,"props":751,"children":753},{"className":752},[],[754],{"type":44,"value":755},"(decl) => true",{"type":44,"value":757},") if they do not call back into Dart or block thread execution.",{"type":38,"tag":58,"props":759,"children":760},{},[761,767,769,775,777,783],{"type":38,"tag":125,"props":762,"children":764},{"className":763},[],[765],{"type":44,"value":766},"recordUse",{"type":44,"value":768},": Enables metadata generation for native asset tree shaking (essential in ",{"type":38,"tag":125,"props":770,"children":772},{"className":771},[],[773],{"type":44,"value":774},"dart-lang\u002Fnative",{"type":44,"value":776},"). Set to ",{"type":38,"tag":125,"props":778,"children":780},{"className":779},[],[781],{"type":44,"value":782},"(_) => true",{"type":44,"value":359},{"type":38,"tag":454,"props":785,"children":787},{"id":786},"_4-output",[788,790],{"type":44,"value":789},"4. ",{"type":38,"tag":125,"props":791,"children":793},{"className":792},[],[794],{"type":44,"value":324},{"type":38,"tag":119,"props":796,"children":797},{},[798],{"type":44,"value":799},"Configures target generated files.",{"type":38,"tag":54,"props":801,"children":802},{},[803,821,837,847],{"type":38,"tag":58,"props":804,"children":805},{},[806,812,814,819],{"type":38,"tag":125,"props":807,"children":809},{"className":808},[],[810],{"type":44,"value":811},"dartFile",{"type":44,"value":813},": Target ",{"type":38,"tag":125,"props":815,"children":817},{"className":816},[],[818],{"type":44,"value":644},{"type":44,"value":820}," where the primary FFI bindings will be written.",{"type":38,"tag":58,"props":822,"children":823},{},[824,829,830,835],{"type":38,"tag":125,"props":825,"children":827},{"className":826},[],[828],{"type":44,"value":403},{"type":44,"value":813},{"type":38,"tag":125,"props":831,"children":833},{"className":832},[],[834],{"type":44,"value":644},{"type":44,"value":836}," for recorded usage metadata maps (crucial for linking-time tree shaking).",{"type":38,"tag":58,"props":838,"children":839},{},[840,845],{"type":38,"tag":125,"props":841,"children":843},{"className":842},[],[844],{"type":44,"value":316},{"type":44,"value":846},": Text inserted at the top of the generated file (licensing, annotations).",{"type":38,"tag":58,"props":848,"children":849},{},[850,856,857,862],{"type":38,"tag":125,"props":851,"children":853},{"className":852},[],[854],{"type":44,"value":855},"format",{"type":44,"value":686},{"type":38,"tag":125,"props":858,"children":860},{"className":859},[],[861],{"type":44,"value":692},{"type":44,"value":863}," to run the Dart formatter automatically.",{"type":38,"tag":47,"props":865,"children":867},{"id":866},"step-by-step-workflow",[868],{"type":44,"value":94},{"type":38,"tag":454,"props":870,"children":872},{"id":871},"step-1-checkadd-dependencies",[873],{"type":44,"value":874},"Step 1: Check\u002FAdd Dependencies",{"type":38,"tag":119,"props":876,"children":877},{},[878,880,886,888,894,896,902,904,912,914,920],{"type":44,"value":879},"Open the package's ",{"type":38,"tag":125,"props":881,"children":883},{"className":882},[],[884],{"type":44,"value":885},"pubspec.yaml",{"type":44,"value":887}," and verify the ",{"type":38,"tag":125,"props":889,"children":891},{"className":890},[],[892],{"type":44,"value":893},"dev_dependencies",{"type":44,"value":895}," contains ",{"type":38,"tag":125,"props":897,"children":899},{"className":898},[],[900],{"type":44,"value":901},"ffigen",{"type":44,"value":903},". Use the Dart MCP server or look up the latest version on ",{"type":38,"tag":62,"props":905,"children":909},{"href":906,"rel":907},"https:\u002F\u002Fpub.dev\u002Fpackages\u002Fffigen",[908],"nofollow",[910],{"type":44,"value":911},"pub.dev",{"type":44,"value":913}," (e.g., ",{"type":38,"tag":125,"props":915,"children":917},{"className":916},[],[918],{"type":44,"value":919},"^20.1.1",{"type":44,"value":241},{"type":38,"tag":119,"props":922,"children":923},{},[924],{"type":44,"value":925},"You can add it automatically using the CLI:",{"type":38,"tag":471,"props":927,"children":931},{"className":928,"code":929,"language":930,"meta":475,"style":475},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","dart pub add dev:ffigen\n","bash",[932],{"type":38,"tag":125,"props":933,"children":934},{"__ignoreMap":475},[935],{"type":38,"tag":481,"props":936,"children":937},{"class":483,"line":484},[938,943,949,954],{"type":38,"tag":481,"props":939,"children":941},{"style":940},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[942],{"type":44,"value":18},{"type":38,"tag":481,"props":944,"children":946},{"style":945},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[947],{"type":44,"value":948}," pub",{"type":38,"tag":481,"props":950,"children":951},{"style":945},[952],{"type":44,"value":953}," add",{"type":38,"tag":481,"props":955,"children":956},{"style":945},[957],{"type":44,"value":958}," dev:ffigen\n",{"type":38,"tag":454,"props":960,"children":962},{"id":961},"step-2-formulate-paths-dynamically",[963],{"type":44,"value":964},"Step 2: Formulate Paths Dynamically",{"type":38,"tag":119,"props":966,"children":967},{},[968,970,976,978,983,985,991],{"type":44,"value":969},"Create a programmatic generator script under the package's ",{"type":38,"tag":125,"props":971,"children":973},{"className":972},[],[974],{"type":44,"value":975},"tool\u002F",{"type":44,"value":977}," directory (e.g., ",{"type":38,"tag":125,"props":979,"children":981},{"className":980},[],[982],{"type":44,"value":206},{"type":44,"value":984},").\nResolve paths relative to ",{"type":38,"tag":125,"props":986,"children":988},{"className":987},[],[989],{"type":44,"value":990},"Platform.script",{"type":44,"value":992}," to make sure it runs successfully from any working directory:",{"type":38,"tag":471,"props":994,"children":996},{"className":473,"code":995,"language":18,"meta":475,"style":475},"final packageRoot = Platform.script.resolve('..\u002F');\nfinal headerFile = packageRoot.resolve('third_party\u002Flibrary.h');\nfinal targetBindings = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fbindings.g.dart');\n",[997],{"type":38,"tag":125,"props":998,"children":999},{"__ignoreMap":475},[1000,1008,1016],{"type":38,"tag":481,"props":1001,"children":1002},{"class":483,"line":484},[1003],{"type":38,"tag":481,"props":1004,"children":1005},{},[1006],{"type":44,"value":1007},"final packageRoot = Platform.script.resolve('..\u002F');\n",{"type":38,"tag":481,"props":1009,"children":1010},{"class":483,"line":493},[1011],{"type":38,"tag":481,"props":1012,"children":1013},{},[1014],{"type":44,"value":1015},"final headerFile = packageRoot.resolve('third_party\u002Flibrary.h');\n",{"type":38,"tag":481,"props":1017,"children":1018},{"class":483,"line":502},[1019],{"type":38,"tag":481,"props":1020,"children":1021},{},[1022],{"type":44,"value":1023},"final targetBindings = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fbindings.g.dart');\n",{"type":38,"tag":454,"props":1025,"children":1027},{"id":1026},"step-3-write-the-script-toolffigendart",[1028,1030,1035],{"type":44,"value":1029},"Step 3: Write the Script (",{"type":38,"tag":125,"props":1031,"children":1033},{"className":1032},[],[1034],{"type":44,"value":206},{"type":44,"value":1036},")",{"type":38,"tag":119,"props":1038,"children":1039},{},[1040,1042,1048,1050,1055],{"type":44,"value":1041},"Define ",{"type":38,"tag":125,"props":1043,"children":1045},{"className":1044},[],[1046],{"type":44,"value":1047},"void main()",{"type":44,"value":1049}," and run ",{"type":38,"tag":125,"props":1051,"children":1053},{"className":1052},[],[1054],{"type":44,"value":138},{"type":44,"value":1056}," with dynamic options (see complete example below).",{"type":38,"tag":454,"props":1058,"children":1060},{"id":1059},"step-4-run-code-generation",[1061],{"type":44,"value":1062},"Step 4: Run Code Generation",{"type":38,"tag":119,"props":1064,"children":1065},{},[1066],{"type":44,"value":1067},"Execute the script from the terminal inside the target package folder:",{"type":38,"tag":471,"props":1069,"children":1071},{"className":928,"code":1070,"language":930,"meta":475,"style":475},"dart run tool\u002Fffigen.dart\n",[1072],{"type":38,"tag":125,"props":1073,"children":1074},{"__ignoreMap":475},[1075],{"type":38,"tag":481,"props":1076,"children":1077},{"class":483,"line":484},[1078,1082,1087],{"type":38,"tag":481,"props":1079,"children":1080},{"style":940},[1081],{"type":44,"value":18},{"type":38,"tag":481,"props":1083,"children":1084},{"style":945},[1085],{"type":44,"value":1086}," run",{"type":38,"tag":481,"props":1088,"children":1089},{"style":945},[1090],{"type":44,"value":1091}," tool\u002Fffigen.dart\n",{"type":38,"tag":454,"props":1093,"children":1095},{"id":1094},"step-5-static-analysis",[1096],{"type":44,"value":1097},"Step 5: Static Analysis",{"type":38,"tag":119,"props":1099,"children":1100},{},[1101,1103,1109],{"type":44,"value":1102},"Verify that the generated bindings are correct and resolve any analysis issues. FFIgen automatically runs the Dart formatter on the output file (via ",{"type":38,"tag":125,"props":1104,"children":1106},{"className":1105},[],[1107],{"type":44,"value":1108},"format: true",{"type":44,"value":1110}," configuration), so manual formatting is not required.",{"type":38,"tag":1112,"props":1113,"children":1114},"ol",{},[1115,1139,1186],{"type":38,"tag":58,"props":1116,"children":1117},{},[1118,1120],{"type":44,"value":1119},"Run the static analyzer inside the target package:\n",{"type":38,"tag":471,"props":1121,"children":1123},{"className":928,"code":1122,"language":930,"meta":475,"style":475},"dart analyze\n",[1124],{"type":38,"tag":125,"props":1125,"children":1126},{"__ignoreMap":475},[1127],{"type":38,"tag":481,"props":1128,"children":1129},{"class":483,"line":484},[1130,1134],{"type":38,"tag":481,"props":1131,"children":1132},{"style":940},[1133],{"type":44,"value":18},{"type":38,"tag":481,"props":1135,"children":1136},{"style":945},[1137],{"type":44,"value":1138}," analyze\n",{"type":38,"tag":58,"props":1140,"children":1141},{},[1142,1147,1149,1154,1156,1162,1164,1169,1171,1177,1178,1184],{"type":38,"tag":153,"props":1143,"children":1144},{},[1145],{"type":44,"value":1146},"Addressing Warnings\u002FLints",{"type":44,"value":1148},": If ",{"type":38,"tag":125,"props":1150,"children":1152},{"className":1151},[],[1153],{"type":44,"value":357},{"type":44,"value":1155}," reports style or lint warnings inside the generated file, append the corresponding warning codes to the ",{"type":38,"tag":125,"props":1157,"children":1159},{"className":1158},[],[1160],{"type":44,"value":1161},"ignore_for_file:",{"type":44,"value":1163}," list in your generator script's ",{"type":38,"tag":125,"props":1165,"children":1167},{"className":1166},[],[1168],{"type":44,"value":316},{"type":44,"value":1170}," configuration (e.g., adding ",{"type":38,"tag":125,"props":1172,"children":1174},{"className":1173},[],[1175],{"type":44,"value":1176},"camel_case_types",{"type":44,"value":175},{"type":38,"tag":125,"props":1179,"children":1181},{"className":1180},[],[1182],{"type":44,"value":1183},"non_constant_identifier_names",{"type":44,"value":1185},", etc.). Do not modify the package's global rules.",{"type":38,"tag":58,"props":1187,"children":1188},{},[1189,1194,1195,1200,1202,1209],{"type":38,"tag":153,"props":1190,"children":1191},{},[1192],{"type":44,"value":1193},"Addressing Compilation Errors",{"type":44,"value":1148},{"type":38,"tag":125,"props":1196,"children":1198},{"className":1197},[],[1199],{"type":44,"value":357},{"type":44,"value":1201}," reports actual compiler or analysis errors (not warnings) inside the generated file, do not attempt to edit the generated file manually. Report these error details directly to the user so they can file an issue on the repository at ",{"type":38,"tag":62,"props":1203,"children":1206},{"href":1204,"rel":1205},"https:\u002F\u002Fgithub.com\u002Fdart-lang\u002Fnative",[908],[1207],{"type":44,"value":1208},"github.com\u002Fdart-lang\u002Fnative",{"type":44,"value":359},{"type":38,"tag":47,"props":1211,"children":1213},{"id":1212},"concrete-example-binding-a-c-library",[1214],{"type":44,"value":103},{"type":38,"tag":119,"props":1216,"children":1217},{},[1218,1220,1226,1228,1234],{"type":44,"value":1219},"Let's assume we are working with the SQLite package under ",{"type":38,"tag":125,"props":1221,"children":1223},{"className":1222},[],[1224],{"type":44,"value":1225},"pkgs\u002Fcode_assets\u002Fexample\u002Fsqlite",{"type":44,"value":1227},", which embeds SQLite C library sources inside ",{"type":38,"tag":125,"props":1229,"children":1231},{"className":1230},[],[1232],{"type":44,"value":1233},"third_party\u002Fsqlite\u002F",{"type":44,"value":1235}," and accesses it via FFI.",{"type":38,"tag":454,"props":1237,"children":1239},{"id":1238},"the-c-header-file-third_partysqlitesqlite3h",[1240,1242,1248],{"type":44,"value":1241},"The C Header File (",{"type":38,"tag":125,"props":1243,"children":1245},{"className":1244},[],[1246],{"type":44,"value":1247},"third_party\u002Fsqlite\u002Fsqlite3.h",{"type":44,"value":1036},{"type":38,"tag":471,"props":1250,"children":1254},{"className":1251,"code":1252,"language":1253,"meta":475,"style":475},"language-c shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F The author disclaims copyright to this source code.\n\n#ifndef SQLITE3_H_\n#define SQLITE3_H_\n\nconst char *sqlite3_libversion(void);\n\n#endif \u002F\u002F SQLITE3_H_\n","c",[1255],{"type":38,"tag":125,"props":1256,"children":1257},{"__ignoreMap":475},[1258,1266,1275,1283,1291,1298,1306,1313],{"type":38,"tag":481,"props":1259,"children":1260},{"class":483,"line":484},[1261],{"type":38,"tag":481,"props":1262,"children":1263},{},[1264],{"type":44,"value":1265},"\u002F\u002F The author disclaims copyright to this source code.\n",{"type":38,"tag":481,"props":1267,"children":1268},{"class":483,"line":493},[1269],{"type":38,"tag":481,"props":1270,"children":1272},{"emptyLinePlaceholder":1271},true,[1273],{"type":44,"value":1274},"\n",{"type":38,"tag":481,"props":1276,"children":1277},{"class":483,"line":502},[1278],{"type":38,"tag":481,"props":1279,"children":1280},{},[1281],{"type":44,"value":1282},"#ifndef SQLITE3_H_\n",{"type":38,"tag":481,"props":1284,"children":1285},{"class":483,"line":511},[1286],{"type":38,"tag":481,"props":1287,"children":1288},{},[1289],{"type":44,"value":1290},"#define SQLITE3_H_\n",{"type":38,"tag":481,"props":1292,"children":1293},{"class":483,"line":520},[1294],{"type":38,"tag":481,"props":1295,"children":1296},{"emptyLinePlaceholder":1271},[1297],{"type":44,"value":1274},{"type":38,"tag":481,"props":1299,"children":1300},{"class":483,"line":529},[1301],{"type":38,"tag":481,"props":1302,"children":1303},{},[1304],{"type":44,"value":1305},"const char *sqlite3_libversion(void);\n",{"type":38,"tag":481,"props":1307,"children":1308},{"class":483,"line":538},[1309],{"type":38,"tag":481,"props":1310,"children":1311},{"emptyLinePlaceholder":1271},[1312],{"type":44,"value":1274},{"type":38,"tag":481,"props":1314,"children":1315},{"class":483,"line":547},[1316,1321],{"type":38,"tag":481,"props":1317,"children":1318},{},[1319],{"type":44,"value":1320},"#endif",{"type":38,"tag":481,"props":1322,"children":1323},{},[1324],{"type":44,"value":1325}," \u002F\u002F SQLITE3_H_\n",{"type":38,"tag":454,"props":1327,"children":1329},{"id":1328},"before-manual-ffi-binding-the-anti-pattern",[1330],{"type":44,"value":1331},"BEFORE: Manual FFI Binding (The Anti-Pattern)",{"type":38,"tag":119,"props":1333,"children":1334},{},[1335],{"type":44,"value":1336},"A developer might attempt to handcraft this integration. It is fragile, blocks tree-shaking metadata, and is highly prone to ABI and structural mapping issues:",{"type":38,"tag":471,"props":1338,"children":1340},{"className":473,"code":1339,"language":18,"meta":475,"style":475},"\u002F\u002F lib\u002Fsrc\u002Fsqlite3_manual.dart\nimport 'dart:ffi' as ffi;\nimport 'package:ffi\u002Fffi.dart';\n\n\u002F\u002F Flaw 1: Hardcoded DynamicLibrary lookup blocks integration with modern native asset compilation.\nfinal ffi.DynamicLibrary _dylib = ffi.DynamicLibrary.open('libsqlite3.so');\n\n\u002F\u002F Flaw 2: Manual function type matching requires writing redundant dynamic lookup boilerplate and lacks tree-shaking metadata.\ntypedef _sqlite3_libversion_C = ffi.Pointer\u003Cffi.Char> Function();\ntypedef _sqlite3_libversion_Dart = ffi.Pointer\u003Cffi.Char> Function();\n\nfinal _sqlite3_libversion_Dart sqlite3LibVersion = _dylib\n    .lookup\u003Cffi.NativeFunction\u003C_sqlite3_libversion_C>>('sqlite3_libversion')\n    .asFunction();\n",[1341],{"type":38,"tag":125,"props":1342,"children":1343},{"__ignoreMap":475},[1344,1352,1360,1368,1375,1383,1391,1398,1406,1414,1422,1429,1437,1445],{"type":38,"tag":481,"props":1345,"children":1346},{"class":483,"line":484},[1347],{"type":38,"tag":481,"props":1348,"children":1349},{},[1350],{"type":44,"value":1351},"\u002F\u002F lib\u002Fsrc\u002Fsqlite3_manual.dart\n",{"type":38,"tag":481,"props":1353,"children":1354},{"class":483,"line":493},[1355],{"type":38,"tag":481,"props":1356,"children":1357},{},[1358],{"type":44,"value":1359},"import 'dart:ffi' as ffi;\n",{"type":38,"tag":481,"props":1361,"children":1362},{"class":483,"line":502},[1363],{"type":38,"tag":481,"props":1364,"children":1365},{},[1366],{"type":44,"value":1367},"import 'package:ffi\u002Fffi.dart';\n",{"type":38,"tag":481,"props":1369,"children":1370},{"class":483,"line":511},[1371],{"type":38,"tag":481,"props":1372,"children":1373},{"emptyLinePlaceholder":1271},[1374],{"type":44,"value":1274},{"type":38,"tag":481,"props":1376,"children":1377},{"class":483,"line":520},[1378],{"type":38,"tag":481,"props":1379,"children":1380},{},[1381],{"type":44,"value":1382},"\u002F\u002F Flaw 1: Hardcoded DynamicLibrary lookup blocks integration with modern native asset compilation.\n",{"type":38,"tag":481,"props":1384,"children":1385},{"class":483,"line":529},[1386],{"type":38,"tag":481,"props":1387,"children":1388},{},[1389],{"type":44,"value":1390},"final ffi.DynamicLibrary _dylib = ffi.DynamicLibrary.open('libsqlite3.so');\n",{"type":38,"tag":481,"props":1392,"children":1393},{"class":483,"line":538},[1394],{"type":38,"tag":481,"props":1395,"children":1396},{"emptyLinePlaceholder":1271},[1397],{"type":44,"value":1274},{"type":38,"tag":481,"props":1399,"children":1400},{"class":483,"line":547},[1401],{"type":38,"tag":481,"props":1402,"children":1403},{},[1404],{"type":44,"value":1405},"\u002F\u002F Flaw 2: Manual function type matching requires writing redundant dynamic lookup boilerplate and lacks tree-shaking metadata.\n",{"type":38,"tag":481,"props":1407,"children":1408},{"class":483,"line":556},[1409],{"type":38,"tag":481,"props":1410,"children":1411},{},[1412],{"type":44,"value":1413},"typedef _sqlite3_libversion_C = ffi.Pointer\u003Cffi.Char> Function();\n",{"type":38,"tag":481,"props":1415,"children":1416},{"class":483,"line":565},[1417],{"type":38,"tag":481,"props":1418,"children":1419},{},[1420],{"type":44,"value":1421},"typedef _sqlite3_libversion_Dart = ffi.Pointer\u003Cffi.Char> Function();\n",{"type":38,"tag":481,"props":1423,"children":1424},{"class":483,"line":574},[1425],{"type":38,"tag":481,"props":1426,"children":1427},{"emptyLinePlaceholder":1271},[1428],{"type":44,"value":1274},{"type":38,"tag":481,"props":1430,"children":1431},{"class":483,"line":583},[1432],{"type":38,"tag":481,"props":1433,"children":1434},{},[1435],{"type":44,"value":1436},"final _sqlite3_libversion_Dart sqlite3LibVersion = _dylib\n",{"type":38,"tag":481,"props":1438,"children":1439},{"class":483,"line":592},[1440],{"type":38,"tag":481,"props":1441,"children":1442},{},[1443],{"type":44,"value":1444},"    .lookup\u003Cffi.NativeFunction\u003C_sqlite3_libversion_C>>('sqlite3_libversion')\n",{"type":38,"tag":481,"props":1446,"children":1447},{"class":483,"line":601},[1448],{"type":38,"tag":481,"props":1449,"children":1450},{},[1451],{"type":44,"value":1452},"    .asFunction();\n",{"type":38,"tag":454,"props":1454,"children":1456},{"id":1455},"after-generating-via-ffigen-the-correct-pattern",[1457],{"type":44,"value":1458},"AFTER: Generating via FFIgen (The Correct Pattern)",{"type":38,"tag":119,"props":1460,"children":1461},{},[1462,1464,1469],{"type":44,"value":1463},"Create a programmatic script at ",{"type":38,"tag":125,"props":1465,"children":1467},{"className":1466},[],[1468],{"type":44,"value":206},{"type":44,"value":452},{"type":38,"tag":471,"props":1471,"children":1473},{"className":473,"code":1472,"language":18,"meta":475,"style":475},"\u002F\u002F Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file\n\u002F\u002F for details. All rights reserved. Use of this source code is governed by a\n\u002F\u002F BSD-style license that can be found in the LICENSE file.\n\nimport 'dart:io';\nimport 'package:ffigen\u002Fffigen.dart';\n\nvoid main() {\n  \u002F\u002F Resolve paths dynamically relative to Platform.script\n  final packageRoot = Platform.script.resolve('..\u002F');\n  final entryHeader = packageRoot.resolve('third_party\u002Fsqlite\u002Fsqlite3.h');\n  final bindingsOutput = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.g.dart');\n  final treeShakeMapping = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.record_use_mapping.g.dart');\n\n  FfiGenerator(\n    headers: Headers(\n      entryPoints: [entryHeader],\n    ),\n    functions: Functions(\n      include: (decl) => {'sqlite3_libversion'}.contains(decl.originalName),\n      \u002F\u002F Essential for package optimization and tree-shaking\n      recordUse: (_) => true,\n    ),\n    output: Output(\n      dartFile: bindingsOutput,\n      recordUseMapping: treeShakeMapping,\n      format: true,\n      preamble: '''\n\n\u002F\u002F AUTO-GENERATED FILE - DO NOT MODIFY.\n\u002F\u002F Generated via ffigen.\n\u002F\u002F To regenerate: dart run tool\u002Fffigen.dart\n\n\u002F\u002F ignore_for_file: type=lint, unused_import, unused_element, deprecated_member_use_from_same_package, experimental_member_use\n''',\n    ),\n  ).generate();\n\n  print('Successfully generated sqlite3 FFI bindings.');\n}\n",[1474],{"type":38,"tag":125,"props":1475,"children":1476},{"__ignoreMap":475},[1477,1485,1493,1501,1508,1516,1524,1531,1539,1547,1555,1563,1571,1579,1586,1595,1604,1613,1622,1631,1640,1649,1658,1666,1675,1684,1693,1702,1711,1719,1728,1737,1746,1754,1763,1772,1780,1789,1797,1806],{"type":38,"tag":481,"props":1478,"children":1479},{"class":483,"line":484},[1480],{"type":38,"tag":481,"props":1481,"children":1482},{},[1483],{"type":44,"value":1484},"\u002F\u002F Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file\n",{"type":38,"tag":481,"props":1486,"children":1487},{"class":483,"line":493},[1488],{"type":38,"tag":481,"props":1489,"children":1490},{},[1491],{"type":44,"value":1492},"\u002F\u002F for details. All rights reserved. Use of this source code is governed by a\n",{"type":38,"tag":481,"props":1494,"children":1495},{"class":483,"line":502},[1496],{"type":38,"tag":481,"props":1497,"children":1498},{},[1499],{"type":44,"value":1500},"\u002F\u002F BSD-style license that can be found in the LICENSE file.\n",{"type":38,"tag":481,"props":1502,"children":1503},{"class":483,"line":511},[1504],{"type":38,"tag":481,"props":1505,"children":1506},{"emptyLinePlaceholder":1271},[1507],{"type":44,"value":1274},{"type":38,"tag":481,"props":1509,"children":1510},{"class":483,"line":520},[1511],{"type":38,"tag":481,"props":1512,"children":1513},{},[1514],{"type":44,"value":1515},"import 'dart:io';\n",{"type":38,"tag":481,"props":1517,"children":1518},{"class":483,"line":529},[1519],{"type":38,"tag":481,"props":1520,"children":1521},{},[1522],{"type":44,"value":1523},"import 'package:ffigen\u002Fffigen.dart';\n",{"type":38,"tag":481,"props":1525,"children":1526},{"class":483,"line":538},[1527],{"type":38,"tag":481,"props":1528,"children":1529},{"emptyLinePlaceholder":1271},[1530],{"type":44,"value":1274},{"type":38,"tag":481,"props":1532,"children":1533},{"class":483,"line":547},[1534],{"type":38,"tag":481,"props":1535,"children":1536},{},[1537],{"type":44,"value":1538},"void main() {\n",{"type":38,"tag":481,"props":1540,"children":1541},{"class":483,"line":556},[1542],{"type":38,"tag":481,"props":1543,"children":1544},{},[1545],{"type":44,"value":1546},"  \u002F\u002F Resolve paths dynamically relative to Platform.script\n",{"type":38,"tag":481,"props":1548,"children":1549},{"class":483,"line":565},[1550],{"type":38,"tag":481,"props":1551,"children":1552},{},[1553],{"type":44,"value":1554},"  final packageRoot = Platform.script.resolve('..\u002F');\n",{"type":38,"tag":481,"props":1556,"children":1557},{"class":483,"line":574},[1558],{"type":38,"tag":481,"props":1559,"children":1560},{},[1561],{"type":44,"value":1562},"  final entryHeader = packageRoot.resolve('third_party\u002Fsqlite\u002Fsqlite3.h');\n",{"type":38,"tag":481,"props":1564,"children":1565},{"class":483,"line":583},[1566],{"type":38,"tag":481,"props":1567,"children":1568},{},[1569],{"type":44,"value":1570},"  final bindingsOutput = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.g.dart');\n",{"type":38,"tag":481,"props":1572,"children":1573},{"class":483,"line":592},[1574],{"type":38,"tag":481,"props":1575,"children":1576},{},[1577],{"type":44,"value":1578},"  final treeShakeMapping = packageRoot.resolve('lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.record_use_mapping.g.dart');\n",{"type":38,"tag":481,"props":1580,"children":1581},{"class":483,"line":601},[1582],{"type":38,"tag":481,"props":1583,"children":1584},{"emptyLinePlaceholder":1271},[1585],{"type":44,"value":1274},{"type":38,"tag":481,"props":1587,"children":1589},{"class":483,"line":1588},15,[1590],{"type":38,"tag":481,"props":1591,"children":1592},{},[1593],{"type":44,"value":1594},"  FfiGenerator(\n",{"type":38,"tag":481,"props":1596,"children":1598},{"class":483,"line":1597},16,[1599],{"type":38,"tag":481,"props":1600,"children":1601},{},[1602],{"type":44,"value":1603},"    headers: Headers(\n",{"type":38,"tag":481,"props":1605,"children":1607},{"class":483,"line":1606},17,[1608],{"type":38,"tag":481,"props":1609,"children":1610},{},[1611],{"type":44,"value":1612},"      entryPoints: [entryHeader],\n",{"type":38,"tag":481,"props":1614,"children":1616},{"class":483,"line":1615},18,[1617],{"type":38,"tag":481,"props":1618,"children":1619},{},[1620],{"type":44,"value":1621},"    ),\n",{"type":38,"tag":481,"props":1623,"children":1625},{"class":483,"line":1624},19,[1626],{"type":38,"tag":481,"props":1627,"children":1628},{},[1629],{"type":44,"value":1630},"    functions: Functions(\n",{"type":38,"tag":481,"props":1632,"children":1634},{"class":483,"line":1633},20,[1635],{"type":38,"tag":481,"props":1636,"children":1637},{},[1638],{"type":44,"value":1639},"      include: (decl) => {'sqlite3_libversion'}.contains(decl.originalName),\n",{"type":38,"tag":481,"props":1641,"children":1643},{"class":483,"line":1642},21,[1644],{"type":38,"tag":481,"props":1645,"children":1646},{},[1647],{"type":44,"value":1648},"      \u002F\u002F Essential for package optimization and tree-shaking\n",{"type":38,"tag":481,"props":1650,"children":1652},{"class":483,"line":1651},22,[1653],{"type":38,"tag":481,"props":1654,"children":1655},{},[1656],{"type":44,"value":1657},"      recordUse: (_) => true,\n",{"type":38,"tag":481,"props":1659,"children":1661},{"class":483,"line":1660},23,[1662],{"type":38,"tag":481,"props":1663,"children":1664},{},[1665],{"type":44,"value":1621},{"type":38,"tag":481,"props":1667,"children":1669},{"class":483,"line":1668},24,[1670],{"type":38,"tag":481,"props":1671,"children":1672},{},[1673],{"type":44,"value":1674},"    output: Output(\n",{"type":38,"tag":481,"props":1676,"children":1678},{"class":483,"line":1677},25,[1679],{"type":38,"tag":481,"props":1680,"children":1681},{},[1682],{"type":44,"value":1683},"      dartFile: bindingsOutput,\n",{"type":38,"tag":481,"props":1685,"children":1687},{"class":483,"line":1686},26,[1688],{"type":38,"tag":481,"props":1689,"children":1690},{},[1691],{"type":44,"value":1692},"      recordUseMapping: treeShakeMapping,\n",{"type":38,"tag":481,"props":1694,"children":1696},{"class":483,"line":1695},27,[1697],{"type":38,"tag":481,"props":1698,"children":1699},{},[1700],{"type":44,"value":1701},"      format: true,\n",{"type":38,"tag":481,"props":1703,"children":1705},{"class":483,"line":1704},28,[1706],{"type":38,"tag":481,"props":1707,"children":1708},{},[1709],{"type":44,"value":1710},"      preamble: '''\n",{"type":38,"tag":481,"props":1712,"children":1714},{"class":483,"line":1713},29,[1715],{"type":38,"tag":481,"props":1716,"children":1717},{"emptyLinePlaceholder":1271},[1718],{"type":44,"value":1274},{"type":38,"tag":481,"props":1720,"children":1722},{"class":483,"line":1721},30,[1723],{"type":38,"tag":481,"props":1724,"children":1725},{},[1726],{"type":44,"value":1727},"\u002F\u002F AUTO-GENERATED FILE - DO NOT MODIFY.\n",{"type":38,"tag":481,"props":1729,"children":1731},{"class":483,"line":1730},31,[1732],{"type":38,"tag":481,"props":1733,"children":1734},{},[1735],{"type":44,"value":1736},"\u002F\u002F Generated via ffigen.\n",{"type":38,"tag":481,"props":1738,"children":1740},{"class":483,"line":1739},32,[1741],{"type":38,"tag":481,"props":1742,"children":1743},{},[1744],{"type":44,"value":1745},"\u002F\u002F To regenerate: dart run tool\u002Fffigen.dart\n",{"type":38,"tag":481,"props":1747,"children":1749},{"class":483,"line":1748},33,[1750],{"type":38,"tag":481,"props":1751,"children":1752},{"emptyLinePlaceholder":1271},[1753],{"type":44,"value":1274},{"type":38,"tag":481,"props":1755,"children":1757},{"class":483,"line":1756},34,[1758],{"type":38,"tag":481,"props":1759,"children":1760},{},[1761],{"type":44,"value":1762},"\u002F\u002F ignore_for_file: type=lint, unused_import, unused_element, deprecated_member_use_from_same_package, experimental_member_use\n",{"type":38,"tag":481,"props":1764,"children":1766},{"class":483,"line":1765},35,[1767],{"type":38,"tag":481,"props":1768,"children":1769},{},[1770],{"type":44,"value":1771},"''',\n",{"type":38,"tag":481,"props":1773,"children":1775},{"class":483,"line":1774},36,[1776],{"type":38,"tag":481,"props":1777,"children":1778},{},[1779],{"type":44,"value":1621},{"type":38,"tag":481,"props":1781,"children":1783},{"class":483,"line":1782},37,[1784],{"type":38,"tag":481,"props":1785,"children":1786},{},[1787],{"type":44,"value":1788},"  ).generate();\n",{"type":38,"tag":481,"props":1790,"children":1792},{"class":483,"line":1791},38,[1793],{"type":38,"tag":481,"props":1794,"children":1795},{"emptyLinePlaceholder":1271},[1796],{"type":44,"value":1274},{"type":38,"tag":481,"props":1798,"children":1800},{"class":483,"line":1799},39,[1801],{"type":38,"tag":481,"props":1802,"children":1803},{},[1804],{"type":44,"value":1805},"  print('Successfully generated sqlite3 FFI bindings.');\n",{"type":38,"tag":481,"props":1807,"children":1809},{"class":483,"line":1808},40,[1810],{"type":38,"tag":481,"props":1811,"children":1812},{},[1813],{"type":44,"value":1814},"}\n",{"type":38,"tag":454,"props":1816,"children":1818},{"id":1817},"running-the-generator-script",[1819],{"type":44,"value":1820},"Running the Generator script",{"type":38,"tag":119,"props":1822,"children":1823},{},[1824],{"type":44,"value":1825},"Run this in the package root directory:",{"type":38,"tag":471,"props":1827,"children":1828},{"className":928,"code":1070,"language":930,"meta":475,"style":475},[1829],{"type":38,"tag":125,"props":1830,"children":1831},{"__ignoreMap":475},[1832],{"type":38,"tag":481,"props":1833,"children":1834},{"class":483,"line":484},[1835,1839,1843],{"type":38,"tag":481,"props":1836,"children":1837},{"style":940},[1838],{"type":44,"value":18},{"type":38,"tag":481,"props":1840,"children":1841},{"style":945},[1842],{"type":44,"value":1086},{"type":38,"tag":481,"props":1844,"children":1845},{"style":945},[1846],{"type":44,"value":1091},{"type":38,"tag":119,"props":1848,"children":1849},{},[1850],{"type":44,"value":1851},"This will automatically create:",{"type":38,"tag":1112,"props":1853,"children":1854},{},[1855,1864],{"type":38,"tag":58,"props":1856,"children":1857},{},[1858],{"type":38,"tag":125,"props":1859,"children":1861},{"className":1860},[],[1862],{"type":44,"value":1863},"lib\u002Fsrc\u002Fthird_party\u002Fsqlite3.g.dart",{"type":38,"tag":58,"props":1865,"children":1866},{},[1867],{"type":38,"tag":125,"props":1868,"children":1870},{"className":1869},[],[1871],{"type":44,"value":432},{"type":38,"tag":47,"props":1873,"children":1875},{"id":1874},"verification-checklist",[1876],{"type":44,"value":112},{"type":38,"tag":119,"props":1878,"children":1879},{},[1880],{"type":44,"value":1881},"Always perform the following verification before completing a binding generation task:",{"type":38,"tag":1112,"props":1883,"children":1884},{},[1885,1909],{"type":38,"tag":58,"props":1886,"children":1887},{},[1888,1893,1895,1900,1902,1907],{"type":38,"tag":153,"props":1889,"children":1890},{},[1891],{"type":44,"value":1892},"Correct Setup",{"type":44,"value":1894},": Verify the target generated files are inside ",{"type":38,"tag":125,"props":1896,"children":1898},{"className":1897},[],[1899],{"type":44,"value":283},{"type":44,"value":1901}," (required for third-party licensed code) and the primary FFI bindings file strictly uses the ",{"type":38,"tag":125,"props":1903,"children":1905},{"className":1904},[],[1906],{"type":44,"value":291},{"type":44,"value":1908}," extension.",{"type":38,"tag":58,"props":1910,"children":1911},{},[1912,1917,1919,1924,1926],{"type":38,"tag":153,"props":1913,"children":1914},{},[1915],{"type":44,"value":1916},"Static Analysis",{"type":44,"value":1918},": Run ",{"type":38,"tag":125,"props":1920,"children":1922},{"className":1921},[],[1923],{"type":44,"value":357},{"type":44,"value":1925}," and ensure there are zero compiler\u002Fanalyzer errors or warnings in the package.\n",{"type":38,"tag":54,"props":1927,"children":1928},{},[1929,1949],{"type":38,"tag":58,"props":1930,"children":1931},{},[1932,1934,1940,1942,1947],{"type":44,"value":1933},"If static warnings are reported in the generated bindings, suppress them by adding ",{"type":38,"tag":125,"props":1935,"children":1937},{"className":1936},[],[1938],{"type":44,"value":1939},"ignore_for_file",{"type":44,"value":1941}," rules to the generator's ",{"type":38,"tag":125,"props":1943,"children":1945},{"className":1944},[],[1946],{"type":44,"value":316},{"type":44,"value":1948}," configuration (do not modify global package rules).",{"type":38,"tag":58,"props":1950,"children":1951},{},[1952,1954,1959],{"type":44,"value":1953},"If actual compiler or analyzer errors are reported in the generated bindings, do not edit the generated file manually. Report the details to the user and direct them to file an issue at ",{"type":38,"tag":62,"props":1955,"children":1957},{"href":1204,"rel":1956},[908],[1958],{"type":44,"value":1208},{"type":44,"value":359},{"type":38,"tag":1961,"props":1962,"children":1963},"style",{},[1964],{"type":44,"value":1965},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1967,"total":1668},[1968,1979,1990,2002,2013,2022,2034],{"slug":1969,"name":1969,"fn":1970,"description":1971,"org":1972,"tags":1973,"stars":19,"repoUrl":20,"updatedAt":1978},"dart-add-unit-test","write unit tests for Dart code","Write and organize unit tests for functions, methods, and classes using `package:test`. Use when creating new logic or fixing bugs to ensure code remains correct and regression-free.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1974,1975],{"name":17,"slug":18,"type":15},{"name":1976,"slug":1977,"type":15},"Testing","testing","2026-07-15T05:22:40.104823",{"slug":1980,"name":1980,"fn":1981,"description":1982,"org":1983,"tags":1984,"stars":19,"repoUrl":20,"updatedAt":1989},"dart-build-cli-app","build Dart command line applications","Entrypoint structure, exit codes, cross-platform scripts. Use when building command line utilities, scripts, or applications.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1985,1988],{"name":1986,"slug":1987,"type":15},"CLI","cli",{"name":17,"slug":18,"type":15},"2026-07-15T05:22:18.863572",{"slug":1991,"name":1991,"fn":1992,"description":1993,"org":1994,"tags":1995,"stars":19,"repoUrl":20,"updatedAt":2001},"dart-collect-coverage","collect Dart test coverage reports","Collect coverage using the coverage packge and create an LCOV report",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1996,1997,2000],{"name":17,"slug":18,"type":15},{"name":1998,"slug":1999,"type":15},"Reporting","reporting",{"name":1976,"slug":1977,"type":15},"2026-07-15T05:22:21.38636",{"slug":2003,"name":2003,"fn":2004,"description":2005,"org":2006,"tags":2007,"stars":19,"repoUrl":20,"updatedAt":2012},"dart-fix-runtime-errors","debug and fix Dart runtime errors","Uses get_runtime_errors and lsp to fetch an active stack trace, locate the failing line, apply a fix, and verify resolution via hot_reload.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2008,2009],{"name":17,"slug":18,"type":15},{"name":2010,"slug":2011,"type":15},"Debugging","debugging","2026-07-15T05:22:22.622501",{"slug":2014,"name":2014,"fn":2015,"description":2016,"org":2017,"tags":2018,"stars":19,"repoUrl":20,"updatedAt":2021},"dart-generate-test-mocks","generate mock objects for Dart tests","Define and generate mock objects for external dependencies using `package:mockito` and `build_runner`. Use when unit testing classes that depend on complex external services like APIs or databases.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2019,2020],{"name":17,"slug":18,"type":15},{"name":1976,"slug":1977,"type":15},"2026-07-15T05:22:42.607449",{"slug":2023,"name":2023,"fn":2024,"description":2025,"org":2026,"tags":2027,"stars":19,"repoUrl":20,"updatedAt":2033},"dart-migrate-to-checks-package","migrate test matchers to checks package","Replace the usage of `expect` and similar functions from `package:matcher`\nto `package:checks` equivalents.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2028,2029,2032],{"name":17,"slug":18,"type":15},{"name":2030,"slug":2031,"type":15},"Migration","migration",{"name":1976,"slug":1977,"type":15},"2026-07-15T05:22:31.276564",{"slug":2035,"name":2035,"fn":2036,"description":2037,"org":2038,"tags":2039,"stars":19,"repoUrl":20,"updatedAt":2043},"dart-resolve-package-conflicts","resolve Dart package version conflicts","Workflow for fixing package version conflicts. Use this when `pub get` fails due to incompatible package versions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2040,2041,2042],{"name":17,"slug":18,"type":15},{"name":2010,"slug":2011,"type":15},{"name":13,"slug":14,"type":15},"2026-07-15T05:22:30.059335",{"items":2045,"total":1695},[2046,2051,2056,2062,2067,2072,2078,2084,2096,2108,2122,2132],{"slug":1969,"name":1969,"fn":1970,"description":1971,"org":2047,"tags":2048,"stars":19,"repoUrl":20,"updatedAt":1978},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2049,2050],{"name":17,"slug":18,"type":15},{"name":1976,"slug":1977,"type":15},{"slug":1980,"name":1980,"fn":1981,"description":1982,"org":2052,"tags":2053,"stars":19,"repoUrl":20,"updatedAt":1989},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2054,2055],{"name":1986,"slug":1987,"type":15},{"name":17,"slug":18,"type":15},{"slug":1991,"name":1991,"fn":1992,"description":1993,"org":2057,"tags":2058,"stars":19,"repoUrl":20,"updatedAt":2001},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2059,2060,2061],{"name":17,"slug":18,"type":15},{"name":1998,"slug":1999,"type":15},{"name":1976,"slug":1977,"type":15},{"slug":2003,"name":2003,"fn":2004,"description":2005,"org":2063,"tags":2064,"stars":19,"repoUrl":20,"updatedAt":2012},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2065,2066],{"name":17,"slug":18,"type":15},{"name":2010,"slug":2011,"type":15},{"slug":2014,"name":2014,"fn":2015,"description":2016,"org":2068,"tags":2069,"stars":19,"repoUrl":20,"updatedAt":2021},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2070,2071],{"name":17,"slug":18,"type":15},{"name":1976,"slug":1977,"type":15},{"slug":2023,"name":2023,"fn":2024,"description":2025,"org":2073,"tags":2074,"stars":19,"repoUrl":20,"updatedAt":2033},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2075,2076,2077],{"name":17,"slug":18,"type":15},{"name":2030,"slug":2031,"type":15},{"name":1976,"slug":1977,"type":15},{"slug":2035,"name":2035,"fn":2036,"description":2037,"org":2079,"tags":2080,"stars":19,"repoUrl":20,"updatedAt":2043},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2081,2082,2083],{"name":17,"slug":18,"type":15},{"name":2010,"slug":2011,"type":15},{"name":13,"slug":14,"type":15},{"slug":2085,"name":2085,"fn":2086,"description":2087,"org":2088,"tags":2089,"stars":19,"repoUrl":20,"updatedAt":2095},"dart-run-static-analysis","run static analysis and apply fixes","Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2090,2093,2094],{"name":2091,"slug":2092,"type":15},"Code Analysis","code-analysis",{"name":17,"slug":18,"type":15},{"name":2010,"slug":2011,"type":15},"2026-07-15T05:22:23.861119",{"slug":2097,"name":2097,"fn":2098,"description":2099,"org":2100,"tags":2101,"stars":19,"repoUrl":20,"updatedAt":2107},"dart-setup-ffi-assets","package C\u002FC++ assets for Dart","Guides agents in compiling and packaging C\u002FC++ source code into dynamic or static libraries (Code Assets) using Dart's Native Assets hook system (via hook\u002Fbuild.dart and hook\u002Flink.dart utilizing package:hooks and package:native_toolchain_c). Use when a user asks to: 'setup native assets', 'compile C\u002FC++ source code', 'bundle dynamic libraries', 'build native C code', 'link native assets', 'implement build.dart or link.dart hooks', or 'integrate C\u002FC++ interop in Dart\u002FFlutter'. Helps agents avoid manual toolchain orchestration and configures secure hash-validated binary downloads or advanced linker tree-shaking with package:record_use mapping.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2102,2103,2106],{"name":17,"slug":18,"type":15},{"name":2104,"slug":2105,"type":15},"Deployment","deployment",{"name":13,"slug":14,"type":15},"2026-07-15T05:22:20.138636",{"slug":2109,"name":2109,"fn":2110,"description":2111,"org":2112,"tags":2113,"stars":19,"repoUrl":20,"updatedAt":2121},"dart-skills-lint-setup","configure dart_skills_lint for Dart projects","Use this skill when you need to set up validation for AI agent skills in a Dart project for the first time.\nAdds the linter as a dev_dependency, creates a configuration file, and generates a baseline for legacy repos.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2114,2115,2118],{"name":17,"slug":18,"type":15},{"name":2116,"slug":2117,"type":15},"Plugin Development","plugin-development",{"name":2119,"slug":2120,"type":15},"QA","qa","2026-07-15T05:22:47.488998",{"slug":2123,"name":2123,"fn":2124,"description":2125,"org":2126,"tags":2127,"stars":19,"repoUrl":20,"updatedAt":2131},"dart-skills-lint-validation","validate agent skills with dart_skills_lint","Use this skill when you need to validate AI agent skills with dart_skills_lint — running the linter, interpreting failures, fixing violations, and authoring custom rules.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2128,2129,2130],{"name":17,"slug":18,"type":15},{"name":2116,"slug":2117,"type":15},{"name":2119,"slug":2120,"type":15},"2026-07-21T05:38:34.451024",{"slug":4,"name":4,"fn":5,"description":6,"org":2133,"tags":2134,"stars":19,"repoUrl":20,"updatedAt":21},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2135,2136],{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15}]