| # FAQ | |
| ## Can FFIgen be used for removing underscores or renaming declarations? | |
| FFIgen supports **regexp-based renaming**. The regexp must be a full match. | |
| For renaming you can use regexp groups (`$1` means group 1). | |
| To renaming `clang_dispose_string` to `string_dispose` we can match it using | |
| `clang_(.*)_(.*)` and rename with `$2_$1`. | |
| Here's an example of how to remove prefix underscores from any struct and its | |
| members. | |
| ```yaml | |
| structs: | |
| ... | |
| rename: | |
| '_(.*)': '$1' # Removes prefix underscores from all structures. | |
| member-rename: | |
| '.*': # Matches any struct. | |
| '_(.*)': '$1' # Removes prefix underscores from members. | |
| ``` | |
| ## How to generate declarations only from particular headers? | |
| The default behavior is to include everything directly/transitively under | |
| each of the `entry-points` specified. | |
| If you only want to have declarations directly particular header you can do so | |
| using `include-directives`. You can use **glob matching** to match header paths. | |
| ```yaml | |
| headers: | |
| entry-points: | |
| - 'path/to/my_header.h' | |
| include-directives: | |
| - '**my_header.h' # This glob pattern matches the header path. | |
| ``` | |
| ## Can FFIgen filter declarations by name? | |
| FFIgen supports including/excluding declarations using full regexp matching. | |
| Here's an example to filter functions using names: | |
| ```yaml | |
| functions: | |
| include: | |
| - 'clang.*' # Include all functions starting with clang. | |
| exclude: | |
| - '.*dispose': # Exclude all functions ending with dispose. | |
| ``` | |
| This will include `clang_help`. But will exclude `clang_dispose`. | |
| Note: exclude overrides include. | |
| ## How does FFIgen handle C Strings? | |
| FFIgen treats `char*` just as any other pointer (`Pointer<Int8>`). | |
| To convert these to/from `String`, you can use [package:ffi](https://pub.dev/packages/ffi). | |
| Use `ptr.cast<Utf8>().toDartString()` to convert `char*` to dart `string` and | |
| `"str".toNativeUtf8()` to convert `string` to `char*`. | |
| ## How are unnamed enums handled? | |
| Unnamed enums are handled separately, under the key `unnamed-enums`, and are | |
| generated as top level constants. | |
| Here's an example that shows how to include/exclude/rename unnamed enums: | |
| ```yaml | |
| unnamed-enums: | |
| include: | |
| - 'CX_.*' | |
| exclude: | |
| - '.*Flag' | |
| rename: | |
| 'CXType_(.*)': '$1' | |
| ``` | |
| ## How can I handle unexpected enum values? | |
| Native enums are, by default, generated into Dart enums with `int get value` and | |
| `fromValue(int)`. This works well in the case that your enums values are known | |
| in advance and not going to change, and in return, you get the full benefits of | |
| Dart enums like exhaustiveness checking. | |
| However, if a native library adds another possible enum value after you generate | |
| your bindings, and this new value is passed to your Dart code, this will result | |
| in an `ArgumentError` at runtime. To fix this, you can regenerate the bindings | |
| on the new header file, but if you wish to avoid this issue entirely, you can | |
| tell FFIgen to generate plain Dart integers for your enum instead. To do this, | |
| simply list your enum's name in the `as-int` section of your FFIgen config: | |
| ```yaml | |
| enums: | |
| as-int: | |
| include: | |
| - MyIntegerEnum | |
| - '*IntegerEnum' | |
| exclude: | |
| - FakeIntegerEnum | |
| ``` | |
| Functions that accept or return these enums will now accept or return integers | |
| instead, and it will be up to your code to map integer values to behavior and | |
| handle invalid values. But your code will be future-proof against new additions | |
| to the enums. | |
| ## Why are some struct/union declarations generated even after excluded them in config? | |
| This happens when an excluded struct/union is a dependency to some included | |
| declaration. (A dependency means a struct is being passed/returned by a function | |
| or is member of another struct in some way.) | |
| Note: If you supply `structs.dependency-only` as `opaque` FFIgen will generate | |
| these struct dependencies as `Opaque` if they were only passed by reference | |
| (pointer). | |
| ```yaml | |
| structs: | |
| dependency-only: opaque | |
| unions: | |
| dependency-only: opaque | |
| ``` | |
| ## How to expose the native pointers? | |
| By default, the native pointers are private, but you can use the | |
| `symbol-address` subkey for functions/globals and make them public by matching | |
| with its name. The pointers are then accessible via `nativeLibrary.addresses`. | |
| Example: | |
| ```yaml | |
| functions: | |
| symbol-address: | |
| include: | |
| - 'myFunc' # Match function name. | |
| - '.*' # Do this to expose all function pointers. | |
| exclude: # If you only use exclude, then everything not excluded is generated. | |
| - 'dispose' | |
| ``` | |
| ## How to get typedefs to Native and Dart type of a function? | |
| By default, these types are inline. But you can use the `expose-typedef` subkey | |
| for functions to generate them. This will expose the Native and Dart type. | |
| E.g. for a function named `hello` the generated typedefs are named as | |
| `NativeHello` and `DartHello`. | |
| Example: | |
| ```yaml | |
| functions: | |
| expose-typedefs: | |
| include: | |
| - 'myFunc' # Match function name. | |
| - '.*' # Do this to expose types for all functions. | |
| exclude: # If you only use exclude, then everything not excluded is generated. | |
| - 'dispose' | |
| ``` | |
| ## How are Structs/Unions/Enums that are referred to via typedefs handled? | |
| Named declarations use their own names even when inside another typedef. | |
| However, unnamed declarations inside typedefs take the name of the _first_ | |
| typedef that refers to them. | |
| ## Why are some typedefs not generated? | |
| The following typedefs are not generated: | |
| - They are not referred to anywhere in the included declarations. | |
| - They refer to a struct/union having the same name as itself. | |
| - They refer to a boolean, enum, inline array, Handle or any unsupported type. | |
| ## How are macros handled? | |
| FFIgen uses `clang`'s own compiler frontend to parse and traverse the `C` | |
| header files. FFIgen expands the macros using `clang`'s macro expansion and | |
| then traverses the expanded code. To do this, FFIgen generates temporary files | |
| in a system tmp directory. | |
| A custom temporary directory can be specified by setting the `TEST_TMPDIR` | |
| environment variable. | |
| ## What are these logs generated by FFIgen and how to fix them? | |
| FFIgen can sometimes generate a lot of logs, especially when it's parsing a lot | |
| of code. | |
| - `SEVERE` logs are something you *definitely need to address*. They can be | |
| caused due to syntax errors, or more generally missing header files | |
| (which need to be specified using `compiler-opts` in config). | |
| - `WARNING` logs are something *you can ignore*, but should probably look into. | |
| These are mostly indications of declarations FFIgen couldn't generate due | |
| to limitations of `dart:ffi`, private declarations (which can be resolved | |
| by renaming them via FFIgen's config) or other minor issues in the config | |
| file itself. | |
| - Everything else can be safely ignored. Its purpose is to simply let you know | |
| what FFIgen is doing. | |
| - The verbosity of the logs can be changed by adding a flag with | |
| the log level, e.g. `dart run ffigen --verbose <level>`. | |
| Level options are `[all, fine, info (default), warning, severe]`. | |
| The `all` and `fine` will print a ton of logs are meant for debugging | |
| purposes only. | |
| ## How can type definitions be shared? | |
| FFIgen can share type definitions using symbol files. | |
| - A package can generate a symbol file using the `output.symbol-file` config. | |
| - And another package can then import this, using `import.symbol-files` config. | |
| - Doing so will reuse all the types such as Struct/Unions, and will automatically | |
| exclude generating other types (E.g. functions, enums, macros). | |
| Checkout `examples/shared_bindings` for details. | |
| For manually reusing definitions from another package, the `library-imports` | |
| and `type-map` config can be used. |