├── test ├── native_objc_test │ ├── .gitignore │ ├── swift_class_test.swift │ ├── cast_config.yaml │ ├── rename_test.m │ ├── forward_decl_test.h │ ├── string_test.m │ ├── method_config.yaml │ ├── string_config.yaml │ ├── nullable_config.yaml │ ├── is_instance_config.yaml │ ├── property_config.yaml │ ├── forward_decl_test.m │ ├── failed_to_load_config.yaml │ ├── block_config.yaml │ ├── failed_to_load_test.m │ ├── typedef_config.yaml │ ├── swift_class_config.yaml │ ├── category_config.yaml │ ├── forward_decl_config.yaml │ ├── inherited_instancetype_config.yaml │ ├── nullable_inheritance_config.yaml │ ├── typedef_test.m │ ├── cast_test.m │ ├── is_instance_test.m │ ├── static_func_config.yaml │ ├── automated_ref_count_config.yaml │ ├── static_func_native_config.yaml │ ├── category_test.m │ ├── inherited_instancetype_test.m │ ├── native_objc_config.yaml │ ├── rename_config.yaml │ ├── bad_method_config.yaml │ ├── nullable_test.m │ ├── rename_test.dart │ ├── forward_decl_test.dart │ ├── property_test.m │ ├── swift_class_test.dart │ ├── util.dart │ ├── typedef_test.dart │ ├── native_objc_test.m │ ├── category_test.dart │ ├── failed_to_load_test.dart │ ├── util.h │ ├── bad_method_test.dart │ ├── bad_method_test.m │ ├── nullable_inheritance_test.m │ ├── method_test.m │ ├── string_test.dart │ ├── static_func_test.m │ ├── is_instance_test.dart │ ├── cast_test.dart │ ├── inherited_instancetype_test.dart │ └── native_objc_test.dart ├── native_test │ ├── .gitignore │ ├── native_test.def │ ├── config.yaml │ └── native_test.c ├── header_parser_tests │ ├── unnamed_enums.h │ ├── regress_384_header_1.h │ ├── regress_384_header_2.h │ ├── separate_definition_base.h │ ├── regress_384_shared.h │ ├── forward_decl.h │ ├── varargs.h │ ├── separate_definition.h │ ├── imported_types.h │ ├── globals.h │ ├── dart_handle.h │ ├── comment_markup.h │ ├── native_func_typedef.h │ ├── functions.h │ ├── expected_bindings │ │ ├── _expected_regress_384_bindings.dart │ │ ├── _expected_packed_structs_bindings.dart │ │ ├── _expected_forward_decl_bindings.dart │ │ └── _expected_comment_markup_bindings.dart │ ├── packed_structs.h │ ├── opaque_dependencies.h │ ├── nested_parsing.h │ ├── unions_test.dart │ ├── forward_decl_test.dart │ ├── packed_structs_test.dart │ ├── macros.h │ ├── unions.h │ ├── function_n_struct.h │ ├── regress_384_test.dart │ ├── comment_markup_test.dart │ ├── imported_types_test.dart │ ├── dart_handle_test.dart │ ├── struct_fptr_fields_test.dart │ ├── native_func_typedef_test.dart │ ├── functions_test.dart │ ├── opaque_dependencies_test.dart │ ├── separate_definition_test.dart │ ├── typedef_test.dart │ ├── varargs_test.dart │ ├── typedef.h │ └── struct_fptr_fields.h ├── code_generator_tests │ └── expected_bindings │ │ ├── _expected_constant_bindings.dart │ │ ├── _expected_enumclass_bindings.dart │ │ ├── _expected_packed_structs_bindings.dart │ │ ├── _expected_struct_bindings.dart │ │ ├── _expected_sort_bindings_bindings.dart │ │ ├── _expected_boolean_dartbool_bindings.dart │ │ ├── _expected_unions_bindings.dart │ │ ├── _expected_function_n_struct_bindings.dart │ │ ├── _expected_global_bindings.dart │ │ └── _expected_typealias_bindings.dart ├── collision_tests │ ├── decl_type_name_collision.h │ ├── expected_bindings │ │ ├── _expected_decl_type_name_collision_bindings.dart │ │ ├── _expected_reserved_keyword_collision_bindings.dart │ │ └── _expected_decl_symbol_address_collision_bindings.dart │ ├── decl_type_name_collision_test.dart │ ├── decl_symbol_address_collision_test.dart │ └── reserved_keyword_collision_test.dart ├── config_tests │ ├── exclude_all_by_default.h │ ├── include_exclude.h │ ├── unknown_keys_warn_test.dart │ ├── compiler_opts_test.dart │ └── packed_struct_override_test.dart ├── example_tests │ ├── cjson_example_test.dart │ ├── ffinative_example_test.dart │ ├── simple_example_test.dart │ ├── libclang_example_test.dart │ ├── shared_bindings_example_test.dart │ └── objective_c_example_test.dart ├── setup.dart └── rename_tests │ └── rename.h ├── example ├── objective_c │ ├── test.mp3 │ ├── pubspec.yaml │ ├── config.yaml │ ├── play_audio.dart │ └── README.md ├── simple │ ├── config.yaml │ ├── .gitignore │ ├── README.md │ ├── pubspec.yaml │ └── headers │ │ └── example.h ├── shared_bindings │ ├── README.md │ ├── .gitignore │ ├── headers │ │ ├── a.h │ │ └── base.h │ ├── pubspec.yaml │ ├── ffigen_configs │ │ ├── a.yaml │ │ ├── a_shared_base.yaml │ │ └── base.yaml │ ├── lib │ │ └── generated │ │ │ ├── base_symbols.yaml │ │ │ ├── base_gen.dart │ │ │ └── a_shared_b_gen.dart │ └── generate.dart ├── c_json │ ├── example.json │ ├── .gitignore │ ├── pubspec.yaml │ ├── README.md │ └── config.yaml ├── ffinative │ ├── .gitignore │ ├── README.md │ ├── config.yaml │ ├── pubspec.yaml │ ├── headers │ │ └── example.h │ └── lib │ │ └── generated_bindings.dart ├── libclang-example │ ├── .gitignore │ ├── pubspec.yaml │ ├── readme.md │ └── custom_import.dart ├── README.md └── swift │ ├── pubspec.yaml │ ├── swift_api.swift │ ├── example.dart │ └── config.yaml ├── AUTHORS ├── bin └── ffigen.dart ├── .github └── dependabot.yml ├── lib ├── src │ ├── config_provider.dart │ ├── header_parser.dart │ ├── code_generator │ │ ├── binding_string.dart │ │ ├── handle.dart │ │ ├── union.dart │ │ ├── struct.dart │ │ ├── dart_keywords.dart │ │ ├── constant.dart │ │ └── binding.dart │ ├── code_generator.dart │ └── header_parser │ │ ├── sub_parsers │ │ ├── objc_block_parser.dart │ │ ├── var_parser.dart │ │ └── function_type_param_parser.dart │ │ ├── type_extractor │ │ └── cxtypekindmap.dart │ │ └── data.dart └── ffigen.dart ├── third_party ├── cjson_library │ ├── .gitignore │ ├── CMakeLists.txt │ └── license.txt ├── sqlite │ └── license.txt └── libclang │ └── include │ └── clang-c │ ├── FatalErrorHandler.h │ ├── Platform.h │ └── ExternC.h ├── tool ├── coverage.sh └── generate_json_schema.dart ├── analysis_options.yaml ├── pubspec.yaml ├── .gitignore ├── CONTRIBUTING.md └── LICENSE /test/native_objc_test/.gitignore: -------------------------------------------------------------------------------- 1 | *_bindings.dart 2 | *-Swift.h 3 | -------------------------------------------------------------------------------- /example/objective_c/test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dart-archive/ffigen/main/example/objective_c/test.mp3 -------------------------------------------------------------------------------- /test/native_test/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore files generated by clang on windows. 2 | native_test.exp 3 | native_test.lib 4 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Below is a list of people and organizations that have contributed 2 | # to the Dart project. Names should be added to the list like so: 3 | # 4 | # Name/Organization 5 | 6 | Google LLC 7 | 8 | Prerak Mann 9 | -------------------------------------------------------------------------------- /example/simple/config.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../ffigen.schema.json 2 | 3 | name: NativeLibrary 4 | description: Bindings to `headers/example.h`. 5 | output: 'generated_bindings.dart' 6 | headers: 7 | entry-points: 8 | - 'headers/example.h' -------------------------------------------------------------------------------- /test/header_parser_tests/unnamed_enums.h: -------------------------------------------------------------------------------- 1 | // Only this should be parsed. 2 | enum{ 3 | A=1, 4 | B=2, // This will be excluded by config. 5 | C=3 6 | }; 7 | 8 | // Shouldn't be parsed. 9 | typedef enum{ 10 | E, 11 | F, 12 | G 13 | } Named; 14 | -------------------------------------------------------------------------------- /example/shared_bindings/README.md: -------------------------------------------------------------------------------- 1 | # Shared bindings 2 | 3 | An example to showcase how bindings can share types 4 | with other bindings. 5 | 6 | ## Generating bindings 7 | At the root of this example (`example/shared_bindings`), run - 8 | ``` 9 | dart run generate.dart 10 | ``` 11 | -------------------------------------------------------------------------------- /test/native_objc_test/swift_class_test.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @objc public class MySwiftClass: NSObject { 4 | var val = 123; 5 | @objc public func getValue() -> Int { 6 | return val; 7 | } 8 | @objc public func setValue(x: Int) { 9 | val = x; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /bin/ffigen.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | // 5 | 6 | export 'package:ffigen/src/executables/ffigen.dart'; 7 | -------------------------------------------------------------------------------- /example/c_json/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CoolGuy", 3 | "age": 21, 4 | "nicknames": [ 5 | { 6 | "name": "Mr. Cool", 7 | "length": 8 8 | }, 9 | { 10 | "name": "Ice Cold", 11 | "length": 8 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_constant_bindings.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: unused_import 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | 8 | const int test1 = 20; 9 | 10 | const double test2 = 20.0; 11 | -------------------------------------------------------------------------------- /test/header_parser_tests/regress_384_header_1.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #include "regress_384_shared.h" 6 | -------------------------------------------------------------------------------- /test/header_parser_tests/regress_384_header_2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #include "regress_384_shared.h" 6 | -------------------------------------------------------------------------------- /example/c_json/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file. 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs. 8 | build/ 9 | 10 | # Directory created by dartdoc. 11 | doc/api/ 12 | -------------------------------------------------------------------------------- /example/simple/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file. 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs. 8 | build/ 9 | 10 | # Directory created by dartdoc. 11 | doc/api/ 12 | -------------------------------------------------------------------------------- /example/ffinative/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file. 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs. 8 | build/ 9 | 10 | # Directory created by dartdoc. 11 | doc/api/ 12 | -------------------------------------------------------------------------------- /example/libclang-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file. 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs. 8 | build/ 9 | 10 | # Directory created by dartdoc. 11 | doc/api/ 12 | -------------------------------------------------------------------------------- /example/shared_bindings/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file. 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs. 8 | build/ 9 | 10 | # Directory created by dartdoc. 11 | doc/api/ 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Dependabot configuration file. 2 | # See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates 3 | version: 2 4 | 5 | updates: 6 | - package-ecosystem: github-actions 7 | directory: / 8 | schedule: 9 | interval: monthly 10 | labels: 11 | - autosubmit 12 | -------------------------------------------------------------------------------- /test/header_parser_tests/separate_definition_base.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct SeparatelyDefinedStruct{ 6 | int a; 7 | int b; 8 | }; 9 | -------------------------------------------------------------------------------- /example/shared_bindings/headers/a.h: -------------------------------------------------------------------------------- 1 | 2 | #include "base.h" 3 | 4 | struct A_Struct1{ 5 | int a; 6 | }; 7 | 8 | union A_Union1{ 9 | int a; 10 | }; 11 | 12 | enum A_Enum{ 13 | A_ENUM_1, 14 | A_ENUM_2, 15 | }; 16 | 17 | #define A_MACRO_1 1; 18 | 19 | void a_func1(); 20 | 21 | void a_func2(struct BaseStruct2 s, union BaseUnion2 u, BaseTypedef2 t); 22 | -------------------------------------------------------------------------------- /lib/src/config_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /// Creates config object used by other sub_modules. 6 | library config_provider; 7 | 8 | export 'config_provider/config.dart'; 9 | -------------------------------------------------------------------------------- /test/header_parser_tests/regress_384_shared.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef __REGRESS_384_SHARED__ 6 | #define __REGRESS_384_SHARED__ 7 | 8 | void foo(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /example/ffinative/README.md: -------------------------------------------------------------------------------- 1 | # Natives example 2 | 3 | A simple example generating `Native` bindings for a very small header file (`headers/example.h`). 4 | 5 | ## Generating bindings 6 | At the root of this example (`example/simple`), run - 7 | ``` 8 | dart run ffigen --config config.yaml 9 | ``` 10 | This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart). 11 | -------------------------------------------------------------------------------- /example/simple/README.md: -------------------------------------------------------------------------------- 1 | # Simple header example 2 | 3 | A very simple example, generates bindings for a very small header file (`headers/example.h`). 4 | 5 | ## Generating bindings 6 | At the root of this example (`example/simple`), run - 7 | ``` 8 | dart run ffigen --config config.yaml 9 | ``` 10 | This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart). 11 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_enumclass_bindings.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: unused_import 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | /// test line 1 8 | /// test line 2 9 | abstract class Constants { 10 | static const int a = 10; 11 | 12 | /// negative 13 | static const int b = -1; 14 | } 15 | -------------------------------------------------------------------------------- /third_party/cjson_library/.gitignore: -------------------------------------------------------------------------------- 1 | # CMake generated files and directories. 2 | CMakeCache.txt 3 | CMakeFiles/ 4 | CmakeScripts/ 5 | Makefile 6 | cmake_install.cmake 7 | 8 | # Xcode tooling generated via `cmake -G Xcode .`. 9 | cjson_library.xcodeproj/ 10 | 11 | # Xcode generated build and output directories. 12 | cjson_library.build/ 13 | 14 | # Generated shared library files. 15 | *.dylib 16 | *.so.* 17 | *.dll 18 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | ## Examples 2 | 3 | - [Simple](https://github.com/dart-lang/ffigen/tree/main/example/simple) 4 | - [cJSON](https://github.com/dart-lang/ffigen/tree/main/example/c_json) 5 | - [LibClang](https://github.com/dart-lang/ffigen/tree/main/example/libclang-example) 6 | - [ObjectiveC](https://github.com/dart-lang/ffigen/tree/main/example/objective_c) 7 | - [Swift](https://github.com/dart-lang/ffigen/tree/main/example/swift) 8 | -------------------------------------------------------------------------------- /test/native_objc_test/cast_config.yaml: -------------------------------------------------------------------------------- 1 | name: CastTestObjCLibrary 2 | description: 'Tests casting objects' 3 | language: objc 4 | output: 'cast_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - Castaway 9 | headers: 10 | entry-points: 11 | - 'cast_test.m' 12 | preamble: | 13 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 14 | -------------------------------------------------------------------------------- /test/native_objc_test/rename_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @interface _Renamed : NSObject 8 | @property int32_t property; 9 | @end 10 | 11 | @implementation _Renamed 12 | @end 13 | -------------------------------------------------------------------------------- /example/ffinative/config.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../ffigen.schema.json 2 | 3 | name: NativeLibrary 4 | ffi-native: 5 | assetId: 'package:ffinative_example/generated_bindings.dart' # (optional) 6 | description: Bindings to `headers/example.h`. 7 | output: 'lib/generated_bindings.dart' 8 | headers: 9 | entry-points: 10 | - 'headers/example.h' 11 | preamble: | 12 | // ignore_for_file: deprecated_member_use 13 | -------------------------------------------------------------------------------- /test/native_objc_test/forward_decl_test.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @class ForwardDeclaredClass; 8 | 9 | @interface OtherClass : NSObject 10 | + (ForwardDeclaredClass*) getTheThing; 11 | @end 12 | -------------------------------------------------------------------------------- /test/native_objc_test/string_test.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | // TODO(#309): strConcat should just be a static function. 5 | @interface StringUtil : NSObject {} 6 | + (NSString*)strConcat:(NSString*)a with:(NSString*)b; 7 | @end 8 | 9 | @implementation StringUtil 10 | + (NSString*)strConcat:(NSString*)a with:(NSString*)b { 11 | return [a stringByAppendingString:b]; 12 | } 13 | @end 14 | -------------------------------------------------------------------------------- /third_party/cjson_library/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7 FATAL_ERROR) 2 | project(cjson_library VERSION 1.0.0 LANGUAGES C) 3 | add_library(cjson_library SHARED cJSON.c) 4 | 5 | set_target_properties(cjson_library PROPERTIES 6 | PUBLIC_HEADER cJSON.h 7 | VERSION ${PROJECT_VERSION} 8 | SOVERSION 1 9 | OUTPUT_NAME "cjson" 10 | XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Hex_Identity_ID_Goes_Here" 11 | ) 12 | -------------------------------------------------------------------------------- /third_party/sqlite/license.txt: -------------------------------------------------------------------------------- 1 | 2001-09-15 2 | 3 | The author disclaims copyright to this source code. In place of 4 | a legal notice, here is a blessing: 5 | 6 | May you do good and not evil. 7 | May you find forgiveness for yourself and forgive others. 8 | May you share freely, never taking more than you give. 9 | 10 | Files generated from sqlite source code are 11 | - test/large_integration_tests/_expected_sqlite_bindings.dart 12 | -------------------------------------------------------------------------------- /lib/src/header_parser.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /// Generates a [Library] (code_generator) 6 | /// 7 | /// Parses the header files AST using clang_bindings. 8 | library header_parser; 9 | 10 | export 'header_parser/parser.dart' show parse; 11 | -------------------------------------------------------------------------------- /test/native_objc_test/method_config.yaml: -------------------------------------------------------------------------------- 1 | name: MethodTestObjCLibrary 2 | description: 'Tests calling Objective-C methods' 3 | language: objc 4 | output: 'method_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - MethodInterface 9 | headers: 10 | entry-points: 11 | - 'method_test.m' 12 | preamble: | 13 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 14 | -------------------------------------------------------------------------------- /test/header_parser_tests/forward_decl.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct A; 6 | enum B; 7 | 8 | void func(struct A *a, enum B b); 9 | 10 | struct A 11 | { 12 | int a; 13 | int b; 14 | }; 15 | 16 | enum B 17 | { 18 | a, 19 | b 20 | }; 21 | -------------------------------------------------------------------------------- /test/native_objc_test/string_config.yaml: -------------------------------------------------------------------------------- 1 | name: StringTestObjCLibrary 2 | description: 'Tests calling Objective-C string methods' 3 | language: objc 4 | output: 'string_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - StringUtil 9 | headers: 10 | entry-points: 11 | - 'string_test.m' 12 | preamble: | 13 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 14 | -------------------------------------------------------------------------------- /example/simple/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: simple_example 6 | 7 | environment: 8 | sdk: ">=3.2.0-210.4.beta <4.0.0" 9 | 10 | dependencies: 11 | ffi: ^2.0.1 12 | dev_dependencies: 13 | ffigen: 14 | path: "../../" 15 | lints: ^2.0.1 16 | -------------------------------------------------------------------------------- /example/swift/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: swift_example 6 | 7 | environment: 8 | sdk: ">=3.2.0-42.1.beta <4.0.0" 9 | 10 | dependencies: 11 | ffi: ^2.0.1 12 | dev_dependencies: 13 | ffigen: 14 | path: "../../" 15 | lints: ^2.0.0 16 | -------------------------------------------------------------------------------- /example/ffinative/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: ffinative_example 6 | 7 | environment: 8 | sdk: ">=3.2.0-210.4.beta <4.0.0" 9 | 10 | dependencies: 11 | ffi: ^2.0.1 12 | dev_dependencies: 13 | ffigen: 14 | path: "../../" 15 | lints: ^2.0.0 16 | -------------------------------------------------------------------------------- /example/objective_c/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: objective_c_example 6 | 7 | environment: 8 | sdk: ">=3.2.0-210.4.beta <4.0.0" 9 | 10 | dependencies: 11 | ffi: ^2.0.1 12 | dev_dependencies: 13 | ffigen: 14 | path: "../../" 15 | lints: ^2.0.0 16 | -------------------------------------------------------------------------------- /test/native_objc_test/nullable_config.yaml: -------------------------------------------------------------------------------- 1 | name: NullableTestObjCLibrary 2 | description: 'Tests nullability for Objective-C methods' 3 | language: objc 4 | output: 'nullable_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - NullableInterface 9 | headers: 10 | entry-points: 11 | - 'nullable_test.m' 12 | preamble: | 13 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 14 | -------------------------------------------------------------------------------- /example/libclang-example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: libclang_example 6 | 7 | environment: 8 | sdk: ">=3.2.0-210.4.beta <4.0.0" 9 | 10 | dependencies: 11 | ffi: ^2.0.1 12 | dev_dependencies: 13 | ffigen: 14 | path: "../../" 15 | lints: ^2.0.1 16 | -------------------------------------------------------------------------------- /example/swift/swift_api.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import Foundation 6 | 7 | @objc public class SwiftClass: NSObject { 8 | @objc public func sayHello() -> String { 9 | return "Hello from Swift!"; 10 | } 11 | 12 | @objc public var someField = 123; 13 | } 14 | -------------------------------------------------------------------------------- /test/header_parser_tests/varargs.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | int myfunc(int a, ...); 6 | void myfunc2(char a, char b, ...); 7 | void myfunc3(long a, ...); 8 | 9 | struct SA { 10 | int a; 11 | }; 12 | 13 | struct Struct_WithLong_Name_test { 14 | int a; 15 | }; 16 | -------------------------------------------------------------------------------- /test/native_objc_test/is_instance_config.yaml: -------------------------------------------------------------------------------- 1 | name: IsInstanceTestObjCLibrary 2 | description: 'Tests isInstance' 3 | language: objc 4 | output: 'is_instance_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - ChildClass 9 | - UnrelatedClass 10 | headers: 11 | entry-points: 12 | - 'is_instance_test.m' 13 | preamble: | 14 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 15 | -------------------------------------------------------------------------------- /example/c_json/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: c_json_example 6 | 7 | environment: 8 | sdk: ">=3.2.0-210.4.beta <4.0.0" 9 | 10 | dependencies: 11 | ffi: ^2.0.1 12 | path: ^1.8.0 13 | 14 | dev_dependencies: 15 | ffigen: 16 | path: "../../" 17 | lints: ^2.0.1 18 | -------------------------------------------------------------------------------- /test/native_objc_test/property_config.yaml: -------------------------------------------------------------------------------- 1 | name: PropertyTestObjCLibrary 2 | description: 'Tests calling Objective-C properties i.e. getters and setters' 3 | language: objc 4 | output: 'property_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - PropertyInterface 9 | headers: 10 | entry-points: 11 | - 'property_test.m' 12 | preamble: | 13 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 14 | -------------------------------------------------------------------------------- /test/native_objc_test/forward_decl_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @interface ForwardDeclaredClass : NSObject 8 | + (int32_t)get123; 9 | @end 10 | 11 | @implementation ForwardDeclaredClass 12 | + (int32_t)get123 { 13 | return 123; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /test/collision_tests/decl_type_name_collision.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct A { 6 | int a; 7 | }; 8 | 9 | struct B { 10 | int B; 11 | int A; 12 | }; 13 | 14 | struct C { 15 | struct A A; 16 | struct B B; 17 | }; 18 | 19 | struct D { 20 | struct B A; 21 | struct A B; 22 | }; 23 | -------------------------------------------------------------------------------- /test/native_objc_test/failed_to_load_config.yaml: -------------------------------------------------------------------------------- 1 | name: FailedToLoadTestObjCLibrary 2 | description: 'Tests failing to load an Objective-C library' 3 | language: objc 4 | output: 'failed_to_load_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - ClassThatWillFailToLoad 9 | headers: 10 | entry-points: 11 | - 'failed_to_load_test.m' 12 | preamble: | 13 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 14 | -------------------------------------------------------------------------------- /test/native_objc_test/block_config.yaml: -------------------------------------------------------------------------------- 1 | name: BlockTestObjCLibrary 2 | description: 'Tests calling Objective-C blocks.' 3 | language: objc 4 | output: 'block_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - BlockTester 9 | functions: 10 | include: 11 | - getBlockRetainCount 12 | headers: 13 | entry-points: 14 | - 'block_test.m' 15 | preamble: | 16 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 17 | -------------------------------------------------------------------------------- /test/native_objc_test/failed_to_load_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @interface ClassThatWillFailToLoad : NSObject {} 8 | -(int32_t)get123; 9 | @end 10 | 11 | @implementation ClassThatWillFailToLoad 12 | -(int32_t)get123 { 13 | return 123; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /test/native_objc_test/typedef_config.yaml: -------------------------------------------------------------------------------- 1 | name: TypedefTestObjCLibrary 2 | description: 'Tests typedef' 3 | language: objc 4 | output: 'typedef_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - SomeClass 9 | - AnotherClass 10 | typedefs: 11 | include: 12 | - SomeClassPtr 13 | headers: 14 | entry-points: 15 | - 'typedef_test.m' 16 | preamble: | 17 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 18 | -------------------------------------------------------------------------------- /example/libclang-example/readme.md: -------------------------------------------------------------------------------- 1 | # Libclang example 2 | 3 | Demonstrates generating bindings for [Libclang](https://clang.llvm.org/doxygen/group__CINDEX.html). 4 | The C header source files for libclang are in [third_party/libclang](/third_party/libclang). 5 | 6 | ## Generating bindings 7 | At the root of this example (`example/libclang-example`), run - 8 | ``` 9 | dart run ffigen --config config.yaml 10 | ``` 11 | This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart). 12 | -------------------------------------------------------------------------------- /test/native_objc_test/swift_class_config.yaml: -------------------------------------------------------------------------------- 1 | name: SwiftClassTestLibrary 2 | description: 'Tests Swift classes' 3 | language: objc 4 | output: 'swift_class_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - MySwiftClass 9 | module: 10 | 'MySwiftClass': 'swift_class_test' 11 | headers: 12 | entry-points: 13 | - 'swift_class_test-Swift.h' 14 | preamble: | 15 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 16 | -------------------------------------------------------------------------------- /example/shared_bindings/pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: shared_bindings 6 | 7 | environment: 8 | sdk: ">=3.2.0-210.4.beta <4.0.0" 9 | 10 | dependencies: 11 | cli_util: ^0.4.0 12 | ffi: ^2.0.1 13 | path: ^1.8.0 14 | 15 | dev_dependencies: 16 | ffigen: 17 | path: "../../" 18 | lints: ^2.0.1 19 | -------------------------------------------------------------------------------- /lib/ffigen.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /// A bindings generator for dart. 6 | /// 7 | /// See complete usage at - https://pub.dev/packages/ffigen. 8 | library ffigen; 9 | 10 | export 'src/code_generator.dart' show Library; 11 | export 'src/config_provider.dart' show Config; 12 | export 'src/header_parser.dart' show parse; 13 | -------------------------------------------------------------------------------- /test/config_tests/exclude_all_by_default.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | void func(); 6 | 7 | struct Struct { 8 | int a; 9 | }; 10 | 11 | union Union { 12 | int a; 13 | }; 14 | 15 | int global; 16 | 17 | #define MACRO 123 18 | 19 | enum Enum { 20 | zero = 0, 21 | }; 22 | 23 | enum { 24 | unnamedEnum = 123, 25 | }; 26 | -------------------------------------------------------------------------------- /test/header_parser_tests/separate_definition.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Forward declaration to SeparatelyDefinedStruct, with definition in 6 | // separate_definition_base.h 7 | struct SeparatelyDefinedStruct; 8 | 9 | void func(struct SeparatelyDefinedStruct s); 10 | 11 | void func2(struct SeparatelyDefinedStruct *s); 12 | -------------------------------------------------------------------------------- /test/native_objc_test/category_config.yaml: -------------------------------------------------------------------------------- 1 | name: CategoryTestObjCLibrary 2 | description: 'Tests handling Objective-C categories' 3 | language: objc 4 | output: 'category_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - Thing 9 | headers: 10 | entry-points: 11 | - 'category_test.m' 12 | # Include it twice, as a regression test for #353 13 | - 'category_test.m' 14 | preamble: | 15 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 16 | -------------------------------------------------------------------------------- /test/native_objc_test/forward_decl_config.yaml: -------------------------------------------------------------------------------- 1 | name: ForwardDeclTestObjCLibrary 2 | description: 'Test that forward declared ObjC classes are correctly filled' 3 | language: objc 4 | output: 'forward_decl_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - ForwardDeclaredClass 9 | headers: 10 | entry-points: 11 | - 'forward_decl_test.h' 12 | - 'forward_decl_test.m' 13 | preamble: | 14 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 15 | -------------------------------------------------------------------------------- /test/native_objc_test/inherited_instancetype_config.yaml: -------------------------------------------------------------------------------- 1 | name: InheritedInstancetypeTestObjCLibrary 2 | description: 'Regression tests for https://github.com/dart-lang/ffigen/issues/486' 3 | language: objc 4 | output: 'inherited_instancetype_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - ChildClass 9 | headers: 10 | entry-points: 11 | - 'inherited_instancetype_test.m' 12 | preamble: | 13 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 14 | -------------------------------------------------------------------------------- /test/native_objc_test/nullable_inheritance_config.yaml: -------------------------------------------------------------------------------- 1 | name: NullableInheritanceTestObjCLibrary 2 | description: 'Tests nullability of inherited Objective-C methods' 3 | language: objc 4 | output: 'nullable_inheritance_bindings.dart' 5 | exclude-all-by-default: true 6 | objc-interfaces: 7 | include: 8 | - NullableBase 9 | - NullableChild 10 | headers: 11 | entry-points: 12 | - 'nullable_inheritance_test.m' 13 | preamble: | 14 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 15 | -------------------------------------------------------------------------------- /test/config_tests/include_exclude.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | typedef int Typedef; 6 | 7 | void func(Typedef s); 8 | 9 | struct Struct { 10 | int a; 11 | }; 12 | 13 | union Union { 14 | int a; 15 | }; 16 | 17 | int global; 18 | 19 | #define MACRO 123 20 | 21 | enum Enum { 22 | zero = 0, 23 | }; 24 | 25 | enum { 26 | unnamedEnum = 123, 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /test/native_objc_test/typedef_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @interface SomeClass : NSObject {} 8 | @end 9 | 10 | @implementation SomeClass 11 | @end 12 | 13 | typedef SomeClass* SomeClassPtr; 14 | 15 | @interface AnotherClass : NSObject {} 16 | @property SomeClassPtr property; 17 | @end 18 | 19 | @implementation AnotherClass 20 | @end 21 | -------------------------------------------------------------------------------- /test/native_test/native_test.def: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | ; for details. All rights reserved. Use of this source code is governed by a 3 | ; BSD-style license that can be found in the LICENSE file. 4 | 5 | EXPORTS 6 | Function1Bool 7 | Function1Uint8 8 | Function1Uint16 9 | Function1Uint32 10 | Function1Uint64 11 | Function1Int8 12 | Function1Int16 13 | Function1Int32 14 | Function1Int64 15 | Function1IntPtr 16 | Function1Float 17 | Function1Double 18 | getStruct1 19 | Function1StructReturnByValue 20 | Function1StructPassByValue 21 | -------------------------------------------------------------------------------- /test/header_parser_tests/imported_types.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #include 6 | 7 | void default_imported_types( 8 | unsigned char, 9 | signed char, 10 | char, 11 | unsigned short, 12 | short, 13 | unsigned int, 14 | int, 15 | unsigned long, 16 | long, 17 | unsigned long long, 18 | long long, 19 | float, 20 | double, 21 | size_t, 22 | wchar_t 23 | ); 24 | -------------------------------------------------------------------------------- /example/shared_bindings/ffigen_configs/a.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # yaml-language-server: $schema=../../../ffigen.schema.json 6 | 7 | name: NativeLibraryA 8 | description: Bindings to `headers/a.h`. 9 | output: '../lib/generated/a_gen.dart' 10 | headers: 11 | entry-points: 12 | - '../headers/a.h' 13 | preamble: | 14 | // ignore_for_file: non_constant_identifier_names, camel_case_types 15 | -------------------------------------------------------------------------------- /test/native_objc_test/cast_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @interface Castaway : NSObject { 8 | } 9 | 10 | - (NSObject *) meAsNSObject; 11 | - (int64_t) meAsInt; 12 | 13 | @end 14 | 15 | @implementation Castaway 16 | 17 | - (NSObject *) meAsNSObject { 18 | return self; 19 | } 20 | 21 | - (int64_t) meAsInt { 22 | return (int64_t) self; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /test/native_objc_test/is_instance_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @interface BaseClass : NSObject {} 8 | @end 9 | 10 | @interface ChildClass : BaseClass {} 11 | @end 12 | 13 | @interface UnrelatedClass : NSObject {} 14 | @end 15 | 16 | @implementation BaseClass 17 | @end 18 | 19 | @implementation ChildClass 20 | @end 21 | 22 | @implementation UnrelatedClass 23 | @end 24 | -------------------------------------------------------------------------------- /test/native_objc_test/static_func_config.yaml: -------------------------------------------------------------------------------- 1 | name: StaticFuncTestObjCLibrary 2 | description: 'Test ObjC static functions' 3 | language: objc 4 | output: 'static_func_bindings.dart' 5 | exclude-all-by-default: true 6 | functions: 7 | include: 8 | - getBlockRetainCount 9 | - staticFuncOfObject 10 | - staticFuncOfNullableObject 11 | - staticFuncOfBlock 12 | - staticFuncReturnsRetained 13 | - staticFuncReturnsRetainedArg 14 | headers: 15 | entry-points: 16 | - 'static_func_test.m' 17 | preamble: | 18 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 19 | -------------------------------------------------------------------------------- /test/native_objc_test/automated_ref_count_config.yaml: -------------------------------------------------------------------------------- 1 | name: AutomatedRefCountTestObjCLibrary 2 | description: 'Tests automatic reference counting of Objective-C objects' 3 | language: objc 4 | output: 'automated_ref_count_bindings.dart' 5 | exclude-all-by-default: true 6 | functions: 7 | include: 8 | - createAutoreleasePool 9 | - destroyAutoreleasePool 10 | objc-interfaces: 11 | include: 12 | - ArcTestObject 13 | - RefCounted 14 | headers: 15 | entry-points: 16 | - 'automated_ref_count_test.m' 17 | preamble: | 18 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 19 | -------------------------------------------------------------------------------- /example/swift/example.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:ffi'; 6 | import 'swift_api_bindings.dart'; 7 | 8 | void main() { 9 | // TODO(#443): Add a test for this. 10 | final lib = SwiftLibrary(DynamicLibrary.open('libswiftapi.dylib')); 11 | final object = SwiftClass.new1(lib); 12 | print(object.sayHello()); 13 | print('field = ${object.someField}'); 14 | object.someField = 456; 15 | print('field = ${object.someField}'); 16 | } 17 | -------------------------------------------------------------------------------- /test/native_objc_test/static_func_native_config.yaml: -------------------------------------------------------------------------------- 1 | name: StaticFuncTestObjCLibrary 2 | description: 'Test ObjC static functions using @Native' 3 | language: objc 4 | output: 'static_func_native_bindings.dart' 5 | exclude-all-by-default: true 6 | ffi-native: 7 | functions: 8 | include: 9 | - getBlockRetainCount 10 | - staticFuncOfObject 11 | - staticFuncOfNullableObject 12 | - staticFuncOfBlock 13 | - staticFuncReturnsRetained 14 | - staticFuncReturnsRetainedArg 15 | headers: 16 | entry-points: 17 | - 'static_func_test.m' 18 | preamble: | 19 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 20 | -------------------------------------------------------------------------------- /example/shared_bindings/lib/generated/base_symbols.yaml: -------------------------------------------------------------------------------- 1 | format_version: 1.0.0 2 | files: 3 | package:shared_bindings/generated/base_gen.dart: 4 | used-config: 5 | ffi-native: false 6 | symbols: 7 | c:@E@BaseEnum: 8 | name: BaseEnum 9 | c:@F@base_func1: 10 | name: base_func1 11 | c:@S@BaseStruct1: 12 | name: BaseStruct1 13 | c:@S@BaseStruct2: 14 | name: BaseStruct2 15 | c:@U@BaseUnion1: 16 | name: BaseUnion1 17 | c:@U@BaseUnion2: 18 | name: BaseUnion2 19 | c:base.h@T@BaseTypedef1: 20 | name: BaseTypedef1 21 | c:base.h@T@BaseTypedef2: 22 | name: BaseTypedef2 23 | -------------------------------------------------------------------------------- /example/c_json/README.md: -------------------------------------------------------------------------------- 1 | # cJson example 2 | 3 | Demonstrates generation of bindings for a C library called 4 | [cJson](https://github.com/DaveGamble/cJSON) and then using these bindings 5 | to parse some json. 6 | 7 | ## Building the cJson dynamic library 8 | From the root of this repository - 9 | ``` 10 | cd third_party/cjson_library 11 | cmake . 12 | make 13 | ``` 14 | 15 | ## Generating bindings 16 | At the root of this example (`example/c_json`), run - 17 | ``` 18 | dart run ffigen --config config.yaml 19 | ``` 20 | This will generate bindings in a file: [cjson_generated_bindings.dart](./cjson_generated_bindings.dart) 21 | 22 | ## Running the example 23 | ``` 24 | dart main.dart 25 | ``` 26 | -------------------------------------------------------------------------------- /example/ffinative/headers/example.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /** Adds 2 integers. */ 6 | int sum(int a, int b); 7 | 8 | /** Subtracts 2 integers. */ 9 | int subtract(int a, int b); 10 | 11 | /** Multiplies 2 integers, returns pointer to an integer,. */ 12 | int *multiply(int a, int b); 13 | 14 | /** Divides 2 integers, returns pointer to a float. */ 15 | float *divide(int a, int b); 16 | 17 | /** Divides 2 floats, returns a pointer to double. */ 18 | double *dividePrecision(float a, float b); 19 | -------------------------------------------------------------------------------- /example/simple/headers/example.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /** Adds 2 integers. */ 6 | int sum(int a, int b); 7 | 8 | /** Subtracts 2 integers. */ 9 | int subtract(int *a, int b); 10 | 11 | /** Multiplies 2 integers, returns pointer to an integer,. */ 12 | int *multiply(int a, int b); 13 | 14 | /** Divides 2 integers, returns pointer to a float. */ 15 | float *divide(int a, int b); 16 | 17 | /** Divides 2 floats, returns a pointer to double. */ 18 | double *dividePrecision(float *a, float *b); 19 | -------------------------------------------------------------------------------- /test/header_parser_tests/globals.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | 8 | bool coolGlobal; 9 | int32_t myInt; 10 | int32_t *aGlobalPointer; 11 | long double longDouble; 12 | long double *pointerToLongDouble; 13 | 14 | // This should be ignored 15 | int GlobalIgnore; 16 | 17 | struct EmptyStruct 18 | { 19 | }; 20 | 21 | struct EmptyStruct globalStruct; 22 | 23 | typedef struct EmptyStruct EmptyStruct_Alias; 24 | EmptyStruct_Alias globalStruct_from_alias; 25 | -------------------------------------------------------------------------------- /example/objective_c/config.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../ffigen.schema.json 2 | 3 | name: AVFAudio 4 | description: Bindings for AVFAudio. 5 | language: objc 6 | output: 'avf_audio_bindings.dart' 7 | exclude-all-by-default: true 8 | objc-interfaces: 9 | include: 10 | - 'AVAudioPlayer' 11 | headers: 12 | entry-points: 13 | - '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AVFAudio.framework/Headers/AVAudioPlayer.h' 14 | preamble: | 15 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field, void_checks, annotate_overrides, no_leading_underscores_for_local_identifiers, library_private_types_in_public_api 16 | -------------------------------------------------------------------------------- /test/header_parser_tests/dart_handle.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #include 6 | 7 | void func1(Dart_Handle); 8 | Dart_Handle func2(); 9 | Dart_Handle **func3(Dart_Handle *); 10 | 11 | typedef void (*Typedef1)(Dart_Handle); 12 | void func4(Typedef1); 13 | 14 | // Dart_Handle isn't supported directly, so all members are removed. 15 | struct Struct1 16 | { 17 | Dart_Handle h; 18 | int a; 19 | }; 20 | 21 | // Pointer works. 22 | struct Struct2 23 | { 24 | Dart_Handle *h; 25 | }; 26 | -------------------------------------------------------------------------------- /test/collision_tests/expected_bindings/_expected_decl_type_name_collision_bindings.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names, 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | import 'dart:ffi' as ffi; 8 | 9 | final class A extends ffi.Struct { 10 | @ffi.Int() 11 | external int a; 12 | } 13 | 14 | final class B extends ffi.Struct { 15 | @ffi.Int() 16 | external int B1; 17 | 18 | @ffi.Int() 19 | external int A; 20 | } 21 | 22 | final class C extends ffi.Struct { 23 | external A A1; 24 | 25 | external B B1; 26 | } 27 | 28 | final class D extends ffi.Struct { 29 | external B A1; 30 | 31 | external A B1; 32 | } 33 | -------------------------------------------------------------------------------- /example/shared_bindings/headers/base.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct BaseStruct1{ 6 | int a; 7 | }; 8 | 9 | union BaseUnion1{ 10 | int a; 11 | }; 12 | 13 | struct BaseStruct2{ 14 | int a; 15 | }; 16 | 17 | union BaseUnion2{ 18 | int a; 19 | }; 20 | 21 | typedef struct BaseStruct1 BaseTypedef1; 22 | typedef struct BaseStruct2 BaseTypedef2; 23 | 24 | enum BaseEnum{ 25 | BASE_ENUM_1, 26 | BASE_ENUM_2, 27 | }; 28 | 29 | #define BASE_MACRO_1 1; 30 | 31 | void base_func1(BaseTypedef1 t1, BaseTypedef2 t2); 32 | -------------------------------------------------------------------------------- /example/swift/config.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../ffigen.schema.json 2 | 3 | name: SwiftLibrary 4 | description: Bindings for swift_api. 5 | language: objc 6 | output: 'swift_api_bindings.dart' 7 | exclude-all-by-default: true 8 | objc-interfaces: 9 | include: 10 | - 'SwiftClass' 11 | module: 12 | 'SwiftClass': 'swift_module' 13 | headers: 14 | entry-points: 15 | - 'third_party/swift_api.h' 16 | preamble: | 17 | // ignore_for_file: camel_case_types, non_constant_identifier_names 18 | // ignore_for_file: unused_element, unused_field, return_of_invalid_type 19 | // ignore_for_file: void_checks, annotate_overrides 20 | // ignore_for_file: no_leading_underscores_for_local_identifiers 21 | // ignore_for_file: library_private_types_in_public_api 22 | -------------------------------------------------------------------------------- /tool/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 4 | # for details. All rights reserved. Use of this source code is governed by a 5 | # BSD-style license that can be found in the LICENSE file. 6 | 7 | # Fast fail the script on failures. 8 | set -e 9 | 10 | # Gather coverage. 11 | dart pub global activate coverage 12 | # Generate coverage report. 13 | dart run --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=3000 test & 14 | dart pub global run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:3000/ -o coverage.json --resume-isolates --scope-output=ffigen 15 | dart pub global run coverage:format_coverage --packages=.dart_tool/package_config.json --lcov -i coverage.json -o lcov.info 16 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | include: package:lints/recommended.yaml 6 | 7 | analyzer: 8 | exclude: 9 | - 'test/**_expected*' 10 | # Goldens cannot be generated outside MacOS causing analysis errors. 11 | - test/native_objc_test/** 12 | language: 13 | strict-casts: true 14 | strict-inference: true 15 | 16 | linter: 17 | rules: 18 | # Enabled. 19 | directives_ordering: true 20 | prefer_final_locals: true 21 | prefer_final_in_for_each: true 22 | use_super_parameters: true 23 | 24 | # Disabled. 25 | constant_identifier_names: false 26 | -------------------------------------------------------------------------------- /lib/src/code_generator/binding_string.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /// A Binding's String representation. 6 | class BindingString { 7 | // Meta data, (not used for generation). 8 | final BindingStringType type; 9 | final String string; 10 | 11 | const BindingString({required this.type, required this.string}); 12 | 13 | @override 14 | String toString() => string; 15 | } 16 | 17 | /// A [BindingString]'s type. 18 | enum BindingStringType { 19 | func, 20 | struct, 21 | union, 22 | constant, 23 | global, 24 | enumClass, 25 | typeDef, 26 | objcInterface, 27 | objcBlock, 28 | } 29 | -------------------------------------------------------------------------------- /test/native_objc_test/category_test.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface Thing : NSObject {} 4 | -(int32_t)add:(int32_t)x Y:(int32_t) y; 5 | @end 6 | 7 | @implementation Thing 8 | -(int32_t)add:(int32_t)x Y:(int32_t) y { 9 | return x + y; 10 | } 11 | @end 12 | 13 | @interface Thing (Sub) 14 | -(int32_t)sub:(int32_t)x Y:(int32_t) y; 15 | @end 16 | 17 | @implementation Thing (Sub) 18 | -(int32_t)sub:(int32_t)x Y:(int32_t) y { 19 | return x - y; 20 | } 21 | @end 22 | 23 | @interface Thing (Mul) 24 | -(int32_t)mul:(int32_t)x Y:(int32_t) y; 25 | 26 | @property (readonly) int32_t someProperty; 27 | @end 28 | 29 | @implementation Thing (Mul) 30 | -(int32_t)mul:(int32_t)x Y:(int32_t) y { 31 | return x * y; 32 | } 33 | 34 | -(int32_t)someProperty { 35 | return 456; 36 | } 37 | @end 38 | -------------------------------------------------------------------------------- /test/header_parser_tests/comment_markup.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /// This is a single line test comment. 6 | void com1(); 7 | 8 | /// This is a multi-line 9 | /// test comment. 10 | void com2(); 11 | 12 | /** This is a multi-line 13 | * doxygen style 14 | * test comment. 15 | */ 16 | void com3(); 17 | 18 | // Test comment for struct. 19 | struct Com4{ 20 | /// Muli-line test comment for struct field 21 | // With multiple line and both // and ///. 22 | int a; 23 | 24 | /* Single line field comment. */ 25 | float b; 26 | 27 | /* Comment on array member. */ 28 | int c[3]; 29 | }; 30 | -------------------------------------------------------------------------------- /example/shared_bindings/ffigen_configs/a_shared_base.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # yaml-language-server: $schema=../../../ffigen.schema.json 6 | 7 | name: NativeLibraryASharedB 8 | description: Bindings to `headers/a.h` with shared definitions from `headers/base.h`. 9 | output: '../lib/generated/a_shared_b_gen.dart' 10 | headers: 11 | entry-points: 12 | - '../headers/a.h' 13 | import: 14 | symbol-files: 15 | # Both package Uri and file paths are supported here. 16 | - 'package:shared_bindings/generated/base_symbols.yaml' 17 | preamble: | 18 | // ignore_for_file: non_constant_identifier_names, camel_case_types 19 | -------------------------------------------------------------------------------- /lib/src/code_generator/handle.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | 7 | import 'writer.dart'; 8 | 9 | /// Represents a Dart_Handle. 10 | class HandleType extends Type { 11 | const HandleType._(); 12 | static const _handle = HandleType._(); 13 | factory HandleType() => _handle; 14 | 15 | @override 16 | String getCType(Writer w) => '${w.ffiLibraryPrefix}.Handle'; 17 | 18 | @override 19 | String getFfiDartType(Writer w) => 'Object'; 20 | 21 | @override 22 | bool get sameFfiDartAndCType => false; 23 | 24 | @override 25 | String toString() => 'Handle'; 26 | } 27 | -------------------------------------------------------------------------------- /test/native_test/config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # =================== GENERATING TEST BINDINGS ================== 6 | # dart run ffigen --config test/native_test/config.yaml 7 | # =============================================================== 8 | 9 | name: NativeLibrary 10 | description: 'Native tests.' 11 | output: '_expected_native_test_bindings.dart' 12 | headers: 13 | entry-points: 14 | - 'native_test.c' 15 | include-directives: 16 | - '**native_test.c' 17 | 18 | compiler-opts: '-Wno-nullability-completeness' 19 | preamble: | 20 | // ignore_for_file: camel_case_types, non_constant_identifier_names 21 | 22 | -------------------------------------------------------------------------------- /test/header_parser_tests/native_func_typedef.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct Struct 6 | { 7 | void (*unnamed1)(void (*unnamed2)()); 8 | }; 9 | 10 | void func(void (*unnamed1)(void (*unnamed2)())); 11 | 12 | // This will be removed because 'long double' is unsupported. 13 | void funcNestedUnimplemented(void (*unnamed1)(void (*unnamed2)(long double))); 14 | 15 | typedef void (*InsideReturnType)(); 16 | typedef InsideReturnType (*WithTypedefReturnType)(); 17 | void funcWithNativeFunc(WithTypedefReturnType named); 18 | 19 | typedef void (*VoidFuncPointer)(); 20 | struct Struct2{ 21 | const VoidFuncPointer constFuncPointer; 22 | }; 23 | -------------------------------------------------------------------------------- /example/shared_bindings/ffigen_configs/base.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # yaml-language-server: $schema=../../../ffigen.schema.json 6 | 7 | name: NativeLibraryBase 8 | description: Bindings to `headers/base.h`. 9 | output: 10 | bindings: '../lib/generated/base_gen.dart' 11 | symbol-file: 12 | # Although file paths are supported here, prefer Package Uri's here. 13 | output: 'package:shared_bindings/generated/base_symbols.yaml' 14 | import-path: 'package:shared_bindings/generated/base_gen.dart' 15 | headers: 16 | entry-points: 17 | - '../headers/base.h' 18 | preamble: | 19 | // ignore_for_file: non_constant_identifier_names, camel_case_types 20 | -------------------------------------------------------------------------------- /test/native_objc_test/inherited_instancetype_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | @interface BaseClass : NSObject {} 8 | + (instancetype)create; 9 | - (instancetype)getSelf; 10 | @end 11 | 12 | @interface ChildClass : BaseClass {} 13 | @property int32_t field; 14 | @end 15 | 16 | @implementation BaseClass 17 | + (instancetype)create { 18 | return [[[self class] alloc] init]; 19 | } 20 | 21 | - (instancetype)getSelf { 22 | return self; 23 | } 24 | @end 25 | 26 | @implementation ChildClass 27 | - (instancetype)init { 28 | if (self = [super init]) { 29 | self.field = 123; 30 | } 31 | return self; 32 | } 33 | @end 34 | -------------------------------------------------------------------------------- /test/native_objc_test/native_objc_config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # =================== GENERATING TEST BINDINGS ================== 6 | # dart run ffigen --config test/native_objc_test/config.yaml 7 | # =============================================================== 8 | 9 | name: NativeObjCLibrary 10 | description: 'Native Objective C test' 11 | language: objc 12 | output: 'native_objc_test_bindings.dart' 13 | exclude-all-by-default: true 14 | objc-interfaces: 15 | include: 16 | - Foo 17 | headers: 18 | entry-points: 19 | - 'native_objc_test.m' 20 | preamble: | 21 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 22 | -------------------------------------------------------------------------------- /test/native_objc_test/rename_config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # =================== GENERATING TEST BINDINGS ================== 6 | # dart run ffigen --config test/rename_test/config.yaml 7 | # =============================================================== 8 | 9 | name: RenameLibrary 10 | description: 'Rename test' 11 | language: objc 12 | output: 'rename_test_bindings.dart' 13 | exclude-all-by-default: true 14 | objc-interfaces: 15 | include: 16 | - _Renamed 17 | rename: 18 | '_(.*)': '$1' 19 | headers: 20 | entry-points: 21 | - 'rename_test.m' 22 | preamble: | 23 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 24 | -------------------------------------------------------------------------------- /test/native_objc_test/bad_method_config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # =================== GENERATING TEST BINDINGS ================== 6 | # dart run ffigen --config test/bad_method_test/config.yaml 7 | # =============================================================== 8 | 9 | name: NativeObjCLibrary 10 | description: 'Native Objective C test' 11 | language: objc 12 | output: 'bad_method_test_bindings.dart' 13 | exclude-all-by-default: true 14 | objc-interfaces: 15 | include: 16 | - 'BadMethodTestObject' 17 | headers: 18 | entry-points: 19 | - 'bad_method_test.m' 20 | preamble: | 21 | // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field 22 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_packed_structs_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | final class NoPacking extends ffi.Struct { 8 | @ffi.Uint8() 9 | external int a; 10 | } 11 | 12 | @ffi.Packed(1) 13 | final class Pack1 extends ffi.Struct { 14 | @ffi.Uint8() 15 | external int a; 16 | } 17 | 18 | @ffi.Packed(2) 19 | final class Pack2 extends ffi.Struct { 20 | @ffi.Uint8() 21 | external int a; 22 | } 23 | 24 | @ffi.Packed(4) 25 | final class Pack21 extends ffi.Struct { 26 | @ffi.Uint8() 27 | external int a; 28 | } 29 | 30 | @ffi.Packed(8) 31 | final class Pack22 extends ffi.Struct { 32 | @ffi.Uint8() 33 | external int a; 34 | } 35 | 36 | @ffi.Packed(16) 37 | final class Pack16 extends ffi.Struct { 38 | @ffi.Uint8() 39 | external int a; 40 | } 41 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_struct_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | /// Just a test struct 8 | /// heres another line 9 | final class NoMember extends ffi.Opaque {} 10 | 11 | final class WithPrimitiveMember extends ffi.Struct { 12 | @ffi.Int32() 13 | external int a; 14 | 15 | @ffi.Double() 16 | external double b; 17 | 18 | @ffi.Uint8() 19 | external int c; 20 | } 21 | 22 | final class WithPointerMember extends ffi.Struct { 23 | external ffi.Pointer a; 24 | 25 | external ffi.Pointer> b; 26 | 27 | @ffi.Uint8() 28 | external int c; 29 | } 30 | 31 | final class WithIntPtrUintPtr extends ffi.Struct { 32 | external ffi.Pointer a; 33 | 34 | external ffi.Pointer> b; 35 | } 36 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | name: ffigen 6 | version: 10.0.0-dev.0 7 | description: > 8 | Generator for FFI bindings, using LibClang to parse C, Objective-C, and Swift 9 | files. 10 | repository: https://github.com/dart-lang/ffigen 11 | 12 | topics: 13 | - interop 14 | - ffi 15 | - codegen 16 | 17 | environment: 18 | sdk: ">=3.2.0-210.4.beta <4.0.0" 19 | 20 | dependencies: 21 | ffi: ^2.0.1 22 | yaml: ^3.0.0 23 | path: ^1.8.0 24 | quiver: ^3.0.0 25 | args: ^2.0.0 26 | logging: ^1.0.0 27 | cli_util: ^0.4.0 28 | glob: ^2.0.0 29 | file: ^7.0.0 30 | package_config: ^2.1.0 31 | yaml_edit: ^2.0.3 32 | 33 | dev_dependencies: 34 | lints: ^2.0.1 35 | test: ^1.16.2 36 | json_schema: ^5.1.1 37 | -------------------------------------------------------------------------------- /example/shared_bindings/generate.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:cli_util/cli_util.dart'; 4 | import 'package:path/path.dart' as p; 5 | 6 | ProcessResult runFfigenForConfig(String sdkPath, String configPath) { 7 | return Process.runSync( 8 | p.join(sdkPath, 'bin', 'dart'), 9 | [ 10 | 'run', 11 | 'ffigen', 12 | '--config=$configPath', 13 | ], 14 | runInShell: Platform.isWindows, 15 | ); 16 | } 17 | 18 | void main() { 19 | final sdkPath = getSdkPath(); 20 | final configPaths = [ 21 | 'ffigen_configs/base.yaml', 22 | 'ffigen_configs/a.yaml', 23 | 'ffigen_configs/a_shared_base.yaml' 24 | ]; 25 | for (final configPath in configPaths) { 26 | final res = runFfigenForConfig(sdkPath, configPath); 27 | print(res.stdout.toString()); 28 | if (res.exitCode != 0) { 29 | throw Exception("Some error occurred: ${res.stderr.toString()}"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/example_tests/cjson_example_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/header_parser.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:path/path.dart' as path; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | void main() { 13 | group('cjson_example_test', () { 14 | setUpAll(() { 15 | logWarnings(Level.SEVERE); 16 | }); 17 | test('c_json', () { 18 | final config = 19 | testConfigFromPath(path.join('example', 'c_json', 'config.yaml')); 20 | final library = parse(config); 21 | 22 | matchLibraryWithExpected( 23 | library, 24 | 'example_c_json.dart', 25 | [config.output], 26 | ); 27 | }); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /test/example_tests/ffinative_example_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/header_parser.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:path/path.dart' as path; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | void main() { 13 | group('ffinative_example_test', () { 14 | setUpAll(() { 15 | logWarnings(Level.SEVERE); 16 | }); 17 | 18 | test('ffinative', () { 19 | final config = 20 | testConfigFromPath(path.join('example', 'ffinative', 'config.yaml')); 21 | final library = parse(config); 22 | 23 | matchLibraryWithExpected( 24 | library, 25 | 'example_ffinative.dart', 26 | [config.output], 27 | ); 28 | }); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /test/header_parser_tests/functions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #include 6 | 7 | // Simple tests with primitives. 8 | void func1(); 9 | int32_t func2(int16_t); 10 | double func3(float, int8_t a, int64_t, int32_t b); 11 | 12 | // Tests with pointers to primitives. 13 | void *func4(int8_t **, double, int32_t ***); 14 | 15 | // Would be treated as `typedef void shortHand(void (*b)())`. 16 | typedef void shortHand(void(b)()); 17 | // Would be treated as `void func5(shortHand *a, void (*b)())`. 18 | void func5(shortHand a, void(b)()); 19 | 20 | // Should be skipped as inline functions are not supported. 21 | static inline void inlineFunc(); 22 | 23 | // Not skipped since it is extern. 24 | extern inline void externInlineFunc(int a); 25 | 26 | char diffChars(unsigned char a, signed char b); 27 | -------------------------------------------------------------------------------- /test/native_objc_test/nullable_test.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NullableInterface : NSObject { 4 | } 5 | 6 | +(BOOL) isNullWithNullableNSObjectArg:(nullable NSObject *)x; 7 | +(BOOL) isNullWithNotNullableNSObjectPtrArg:(NSObject *)x; 8 | +(BOOL) isNullWithExplicitNonNullableNSObjectPtrArg:(nonnull NSObject *)x; 9 | +(nullable NSObject *) returnNil:(BOOL)r; 10 | 11 | @property (nullable, retain) NSObject *nullableObjectProperty; 12 | 13 | @end 14 | 15 | @implementation NullableInterface 16 | 17 | +(BOOL) isNullWithNullableNSObjectArg:(nullable NSObject *)x { 18 | return x == NULL; 19 | } 20 | 21 | +(BOOL) isNullWithNotNullableNSObjectPtrArg:(NSObject *)x { 22 | return x == NULL; 23 | } 24 | 25 | +(BOOL) isNullWithExplicitNonNullableNSObjectPtrArg:(nonnull NSObject *)x { 26 | return x == NULL; 27 | } 28 | 29 | +(nullable NSObject *) returnNil:(BOOL)r { 30 | if (r) { 31 | return nil; 32 | } else { 33 | return [NSObject new]; 34 | } 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /test/example_tests/simple_example_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/header_parser.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:path/path.dart' as path; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | void main() { 13 | group('simple_example_test', () { 14 | setUpAll(() { 15 | logWarnings(Level.SEVERE); 16 | }); 17 | 18 | test('simple', () { 19 | final config = testConfigFromPath(path.join( 20 | 'example', 21 | 'simple', 22 | 'config.yaml', 23 | )); 24 | final library = parse(config); 25 | 26 | matchLibraryWithExpected( 27 | library, 28 | 'example_simple.dart', 29 | [config.output], 30 | ); 31 | }); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /test/header_parser_tests/expected_bindings/_expected_regress_384_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | /// Regression test for #384 8 | class NativeLibrary { 9 | /// Holds the symbol lookup function. 10 | final ffi.Pointer Function(String symbolName) 11 | _lookup; 12 | 13 | /// The symbols are looked up in [dynamicLibrary]. 14 | NativeLibrary(ffi.DynamicLibrary dynamicLibrary) 15 | : _lookup = dynamicLibrary.lookup; 16 | 17 | /// The symbols are looked up with [lookup]. 18 | NativeLibrary.fromLookup( 19 | ffi.Pointer Function(String symbolName) 20 | lookup) 21 | : _lookup = lookup; 22 | 23 | void foo() { 24 | return _foo(); 25 | } 26 | 27 | late final _fooPtr = _lookup>('foo'); 28 | late final _foo = _fooPtr.asFunction(); 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/code_generator/union.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator/compound.dart'; 6 | 7 | /// A binding for a C union - 8 | /// 9 | /// ```c 10 | /// union C { 11 | /// int a; 12 | /// double b; 13 | /// float c; 14 | /// }; 15 | /// ``` 16 | /// The generated dart code is - 17 | /// ```dart 18 | /// final class Union extends ffi.Union{ 19 | /// @ffi.Int32() 20 | /// int a; 21 | /// 22 | /// @ffi.Double() 23 | /// double b; 24 | /// 25 | /// @ffi.Float() 26 | /// float c; 27 | /// 28 | /// } 29 | /// ``` 30 | class Union extends Compound { 31 | Union({ 32 | super.usr, 33 | super.originalName, 34 | required super.name, 35 | super.isIncomplete, 36 | super.pack, 37 | super.dartDoc, 38 | super.members, 39 | }) : super(compoundType: CompoundType.union); 40 | } 41 | -------------------------------------------------------------------------------- /test/header_parser_tests/packed_structs.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct NormalStruct1 6 | { 7 | char a; 8 | }; 9 | 10 | /// Should not be packed. 11 | struct StructWithAttr 12 | { 13 | int *a; 14 | int *b; 15 | } __attribute__((annotate("Attr is not __packed__"))); 16 | 17 | /// Should be packed with 1. 18 | struct PackedAttr{ 19 | int a; 20 | } __attribute__((__packed__)); 21 | 22 | /// Should be packed with 8. 23 | struct PackedAttrAlign8{ 24 | int a; 25 | } __attribute__((__packed__, aligned(8))); 26 | 27 | #pragma pack(push, 2) 28 | /// Should be packed with 2. 29 | struct Pack2WithPragma{ 30 | int a; 31 | }; 32 | #pragma pack(4) 33 | /// Should be packed with 4. 34 | struct Pack4WithPragma{ 35 | long long a; 36 | }; 37 | #pragma pack(pop) 38 | struct NormalStruct2 39 | { 40 | char a; 41 | }; 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://dart.dev/guides/libraries/private-files 2 | 3 | # Files and directories created by pub. 4 | .dart_tool/ 5 | .packages 6 | pubspec.lock 7 | 8 | # IDE and debugger files. 9 | .clangd 10 | .gdb_history 11 | .history 12 | .vscode 13 | compile_commands.json 14 | 15 | # Directory created by dartdoc. 16 | # If you don't generate documentation locally you can remove this line. 17 | doc/api/ 18 | 19 | # Avoid committing generated Javascript files: 20 | *.dart.js 21 | *.info.json # Produced by the --dump-info flag. 22 | *.js # When generated by dart2js. Don't specify *.js if your 23 | # project includes source files written in JavaScript. 24 | *.js_ 25 | *.js.deps 26 | *.js.map 27 | 28 | # Generated shared libraries. 29 | *.so 30 | *.so.* 31 | *.dylib 32 | *.dll 33 | 34 | # Directory for quick experiments. 35 | experiments/ 36 | 37 | # Files generated by tests for debugging purposes. 38 | test/debug_generated/* 39 | !test/debug_generated/readme.md 40 | lcov.info 41 | coverage.json 42 | 43 | # Files generated by various OSs. 44 | .DS_Store 45 | -------------------------------------------------------------------------------- /lib/src/code_generator/struct.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator/compound.dart'; 6 | 7 | /// A binding for C Struct. 8 | /// 9 | /// For a C structure - 10 | /// ```c 11 | /// struct C { 12 | /// int a; 13 | /// double b; 14 | /// int c; 15 | /// }; 16 | /// ``` 17 | /// The generated dart code is - 18 | /// ```dart 19 | /// final class Struct extends ffi.Struct { 20 | /// @ffi.Int32() 21 | /// int a; 22 | /// 23 | /// @ffi.Double() 24 | /// double b; 25 | /// 26 | /// @ffi.Uint8() 27 | /// int c; 28 | /// 29 | /// } 30 | /// ``` 31 | class Struct extends Compound { 32 | Struct({ 33 | super.usr, 34 | super.originalName, 35 | required super.name, 36 | super.isIncomplete, 37 | super.pack, 38 | super.dartDoc, 39 | super.members, 40 | super.isInternal, 41 | }) : super(compoundType: CompoundType.struct); 42 | } 43 | -------------------------------------------------------------------------------- /test/native_objc_test/rename_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'rename_test_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late RenameLibrary lib; 18 | group('rename_test', () { 19 | setUpAll(() { 20 | logWarnings(); 21 | final dylib = File('test/native_objc_test/rename_test.dylib'); 22 | verifySetupFile(dylib); 23 | lib = RenameLibrary(DynamicLibrary.open(dylib.absolute.path)); 24 | generateBindingsForCoverage('rename'); 25 | }); 26 | 27 | test('Renamed class', () { 28 | final renamed = Renamed.new1(lib); 29 | renamed.property = 123; 30 | expect(renamed.property, 123); 31 | }); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /test/native_objc_test/forward_decl_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'forward_decl_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late ForwardDeclTestObjCLibrary lib; 18 | 19 | group('forward decl', () { 20 | setUpAll(() { 21 | logWarnings(); 22 | final dylib = File('test/native_objc_test/forward_decl_test.dylib'); 23 | verifySetupFile(dylib); 24 | lib = 25 | ForwardDeclTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 26 | generateBindingsForCoverage('forward_decl'); 27 | }); 28 | 29 | test('Forward declared class', () { 30 | expect(ForwardDeclaredClass.get123(lib), 123); 31 | }); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /test/header_parser_tests/opaque_dependencies.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Opaque. 6 | struct A 7 | { 8 | int a; 9 | }; 10 | 11 | // Opaque. 12 | typedef struct B 13 | { 14 | int a; 15 | } BAlias; 16 | 17 | BAlias *func(struct A *a); 18 | 19 | // Opaque. 20 | struct C 21 | { 22 | int a; 23 | }; 24 | 25 | // Full (excluded, but used by value). 26 | struct D 27 | { 28 | int a; 29 | }; 30 | 31 | // Full (included) 32 | struct E 33 | { 34 | struct C *c; 35 | struct D d; 36 | }; 37 | 38 | // Opaque. 39 | union UA 40 | { 41 | int a; 42 | }; 43 | 44 | // Opaque. 45 | union UB 46 | { 47 | int a; 48 | }; 49 | 50 | union UB *func2(union UA *a); 51 | 52 | // Opaque. 53 | union UC 54 | { 55 | int a; 56 | }; 57 | 58 | // Full (excluded, but used by value). 59 | union UD 60 | { 61 | int a; 62 | }; 63 | 64 | // Full (included) 65 | union UE 66 | { 67 | union UC *c; 68 | union UD d; 69 | }; 70 | -------------------------------------------------------------------------------- /test/native_objc_test/property_test.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class UndefinedTemplate; 4 | 5 | typedef struct { 6 | double x; 7 | double y; 8 | double z; 9 | double w; 10 | } Vec4; 11 | 12 | @interface PropertyInterface : NSObject { 13 | } 14 | 15 | @property (readonly) int32_t readOnlyProperty; 16 | @property int32_t readWriteProperty; 17 | @property (class, readonly, copy) UndefinedTemplate *regressGH436; 18 | @property (class, readonly) int32_t classReadOnlyProperty; 19 | @property (class) int32_t classReadWriteProperty; 20 | @property float floatProperty; 21 | @property double doubleProperty; 22 | @property Vec4 structProperty; 23 | 24 | @end 25 | 26 | @implementation PropertyInterface 27 | 28 | static int32_t _classReadWriteProperty = 0; 29 | 30 | - (int32_t)readOnlyProperty { 31 | return 7; 32 | } 33 | 34 | + (int32_t)classReadOnlyProperty { 35 | return 42; 36 | } 37 | 38 | + (int32_t)classReadWriteProperty { 39 | return _classReadWriteProperty; 40 | } 41 | 42 | + (void)setClassReadWriteProperty:(int32_t)x { 43 | _classReadWriteProperty = x; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /tool/generate_json_schema.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // ================== GENERATING JSON SCHEMA ===================== 6 | // cd to project's root, and run - 7 | // dart generate_json_schema.dart 8 | // =============================================================== 9 | import 'dart:convert'; 10 | import 'dart:io'; 11 | 12 | import 'package:ffigen/ffigen.dart'; 13 | import 'package:ffigen/src/strings.dart' as strings; 14 | 15 | void main() async { 16 | final actualJsonSchema = 17 | JsonEncoder.withIndent(strings.ffigenJsonSchemaIndent).convert( 18 | Config.getsRootConfigSpec().generateJsonSchema(strings.ffigenJsonSchemaId), 19 | ); 20 | 21 | final file = File(strings.ffigenJsonSchemaFileName); 22 | if (!await file.exists()) { 23 | throw Exception("File '${file.absolute.path}' does not exist."); 24 | } 25 | await file.writeAsString(actualJsonSchema); 26 | 27 | print("Generated json schema: ${file.absolute.path}"); 28 | } 29 | -------------------------------------------------------------------------------- /example/objective_c/play_audio.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:ffi'; 6 | import 'avf_audio_bindings.dart'; 7 | 8 | const _dylibPath = 9 | '/System/Library/Frameworks/AVFAudio.framework/Versions/Current/AVFAudio'; 10 | 11 | void main(List args) async { 12 | final lib = AVFAudio(DynamicLibrary.open(_dylibPath)); 13 | for (final file in args) { 14 | final fileStr = NSString(lib, file); 15 | print('Loading $fileStr'); 16 | final fileUrl = NSURL.fileURLWithPath_(lib, fileStr); 17 | final player = 18 | AVAudioPlayer.alloc(lib).initWithContentsOfURL_error_(fileUrl, nullptr); 19 | final durationSeconds = player.duration.ceil(); 20 | print('$durationSeconds sec'); 21 | final status = player.play(); 22 | if (status) { 23 | print('Playing...'); 24 | await Future.delayed(Duration(seconds: durationSeconds)); 25 | } else { 26 | print('Failed to play audio.'); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/header_parser_tests/nested_parsing.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct Struct2 6 | { 7 | int e; 8 | int f; 9 | }; 10 | 11 | struct Struct1 12 | { 13 | int a; 14 | int b; 15 | struct Struct2 *struct2; 16 | }; 17 | 18 | struct Struct3 19 | { 20 | int a; 21 | // An unnamed struct. 22 | struct 23 | { 24 | int a; 25 | int b; 26 | } b; 27 | }; 28 | 29 | struct EmptyStruct{ 30 | }; 31 | 32 | struct Struct4{ 33 | int a; 34 | // Incomplete struct inside a struct. 35 | struct EmptyStruct b; 36 | }; 37 | 38 | struct Struct5{ 39 | int a; 40 | // Incomplete struct array. 41 | struct EmptyStruct b[3]; 42 | }; 43 | 44 | struct Struct6 45 | { 46 | // An anonymous, unnamed union. 47 | union 48 | { 49 | float a; 50 | }; 51 | 52 | // An unnamed union. 53 | union 54 | { 55 | float b; 56 | } c; 57 | 58 | union 59 | { 60 | float d; 61 | } e; 62 | }; 63 | -------------------------------------------------------------------------------- /test/native_objc_test/swift_class_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'swift_class_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late SwiftClassTestLibrary lib; 18 | group('swift_class_test', () { 19 | setUpAll(() { 20 | logWarnings(); 21 | final dylib = File('test/native_objc_test/swift_class_test.dylib'); 22 | verifySetupFile(dylib); 23 | lib = SwiftClassTestLibrary(DynamicLibrary.open(dylib.absolute.path)); 24 | generateBindingsForCoverage('swift_class'); 25 | }); 26 | 27 | test('Renamed class', () { 28 | final swiftObject = MySwiftClass.new1(lib); 29 | expect(swiftObject.getValue(), 123); 30 | swiftObject.setValueWithX_(456); 31 | expect(swiftObject.getValue(), 456); 32 | }); 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/code_generator.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /// Generates FFI bindings for a given [Library]. 6 | library code_generator; 7 | 8 | export 'code_generator/binding.dart'; 9 | export 'code_generator/compound.dart'; 10 | export 'code_generator/constant.dart'; 11 | export 'code_generator/enum_class.dart'; 12 | export 'code_generator/func.dart'; 13 | export 'code_generator/func_type.dart'; 14 | export 'code_generator/global.dart'; 15 | export 'code_generator/handle.dart'; 16 | export 'code_generator/imports.dart'; 17 | export 'code_generator/library.dart'; 18 | export 'code_generator/native_type.dart'; 19 | export 'code_generator/objc_block.dart'; 20 | export 'code_generator/objc_built_in_functions.dart'; 21 | export 'code_generator/objc_interface.dart'; 22 | export 'code_generator/objc_nullable.dart'; 23 | export 'code_generator/pointer.dart'; 24 | export 'code_generator/struct.dart'; 25 | export 'code_generator/type.dart'; 26 | export 'code_generator/typealias.dart'; 27 | export 'code_generator/union.dart'; 28 | -------------------------------------------------------------------------------- /test/native_objc_test/util.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:ffigen/ffigen.dart'; 8 | import 'package:path/path.dart' as path; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | void generateBindingsForCoverage(String testName) { 14 | // The ObjC test bindings are generated in setup.dart (see #362), which means 15 | // that the ObjC related bits of ffigen are missed by test coverage. So this 16 | // function just regenerates those bindings. It doesn't test anything except 17 | // that the generation succeeded, by asserting the file exists. 18 | final config = testConfig( 19 | File(path.join('test', 'native_objc_test', '${testName}_config.yaml')) 20 | .readAsStringSync()); 21 | final library = parse(config); 22 | final file = File( 23 | path.join('test', 'debug_generated', '${testName}_test.dart'), 24 | ); 25 | library.generateFile(file); 26 | assert(file.existsSync()); 27 | file.delete(); 28 | } 29 | -------------------------------------------------------------------------------- /test/header_parser_tests/expected_bindings/_expected_packed_structs_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | final class NormalStruct1 extends ffi.Struct { 8 | @ffi.Char() 9 | external int a; 10 | } 11 | 12 | /// Should not be packed. 13 | final class StructWithAttr extends ffi.Struct { 14 | external ffi.Pointer a; 15 | 16 | external ffi.Pointer b; 17 | } 18 | 19 | /// Should be packed with 1. 20 | @ffi.Packed(1) 21 | final class PackedAttr extends ffi.Struct { 22 | @ffi.Int() 23 | external int a; 24 | } 25 | 26 | /// Should be packed with 8. 27 | @ffi.Packed(8) 28 | final class PackedAttrAlign8 extends ffi.Struct { 29 | @ffi.Int() 30 | external int a; 31 | } 32 | 33 | /// Should be packed with 2. 34 | @ffi.Packed(2) 35 | final class Pack2WithPragma extends ffi.Struct { 36 | @ffi.Int() 37 | external int a; 38 | } 39 | 40 | /// Should be packed with 4. 41 | @ffi.Packed(4) 42 | final class Pack4WithPragma extends ffi.Struct { 43 | @ffi.LongLong() 44 | external int a; 45 | } 46 | 47 | final class NormalStruct2 extends ffi.Struct { 48 | @ffi.Char() 49 | external int a; 50 | } 51 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_sort_bindings_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | class Bindings { 8 | /// Holds the symbol lookup function. 9 | final ffi.Pointer Function(String symbolName) 10 | _lookup; 11 | 12 | /// The symbols are looked up in [dynamicLibrary]. 13 | Bindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; 14 | 15 | /// The symbols are looked up with [lookup]. 16 | Bindings.fromLookup( 17 | ffi.Pointer Function(String symbolName) 18 | lookup) 19 | : _lookup = lookup; 20 | 21 | void a() { 22 | return _a(); 23 | } 24 | 25 | late final _aPtr = _lookup>('a'); 26 | late final _a = _aPtr.asFunction(); 27 | 28 | void b() { 29 | return _b(); 30 | } 31 | 32 | late final _bPtr = _lookup>('b'); 33 | late final _b = _bPtr.asFunction(); 34 | } 35 | 36 | final class C extends ffi.Opaque {} 37 | 38 | final class D extends ffi.Opaque {} 39 | -------------------------------------------------------------------------------- /test/setup.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Runs all the test setup scripts. Usage: 6 | // dart run test/setup.dart 7 | 8 | import 'dart:async'; 9 | import 'dart:io'; 10 | 11 | Future _run(String subdir, String script) async { 12 | final dir = Platform.script.resolve('$subdir/'); 13 | print('\nRunning $script in ${dir.toFilePath()}'); 14 | final args = ['run', dir.resolve(script).toFilePath()]; 15 | final process = await Process.start( 16 | Platform.executable, 17 | args, 18 | workingDirectory: dir.toFilePath(), 19 | ); 20 | unawaited(stdout.addStream(process.stdout)); 21 | unawaited(stderr.addStream(process.stderr)); 22 | final result = await process.exitCode; 23 | if (result != 0) { 24 | throw ProcessException(Platform.executable, args, '$script failed', result); 25 | } 26 | } 27 | 28 | Future main() async { 29 | await _run('native_test', 'build_test_dylib.dart'); 30 | if (Platform.isMacOS) { 31 | await _run('native_objc_test', 'setup.dart'); 32 | } 33 | print('\nSuccess :)\n'); 34 | } 35 | -------------------------------------------------------------------------------- /test/native_objc_test/typedef_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'typedef_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late TypedefTestObjCLibrary lib; 18 | 19 | group('typedef', () { 20 | setUpAll(() { 21 | logWarnings(); 22 | final dylib = File('test/native_objc_test/typedef_test.dylib'); 23 | verifySetupFile(dylib); 24 | lib = TypedefTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 25 | generateBindingsForCoverage('typedef'); 26 | }); 27 | 28 | test('Regression test for #386', () { 29 | // https://github.com/dart-lang/ffigen/issues/386 30 | // Make sure that the typedef DartSomeClassPtr is for SomeClass. 31 | final DartSomeClassPtr instance = SomeClass.new1(lib); 32 | expect(instance.pointer, isNot(nullptr)); 33 | }); 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /test/native_objc_test/native_objc_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | #import 7 | 8 | @interface Foo : NSObject { 9 | double doubleVal; 10 | } 11 | 12 | @property int32_t intVal; 13 | @property BOOL boolVal; 14 | @property id idVal; 15 | @property SEL selVal; 16 | @property NSObject* objVal; 17 | @property Class classVal; 18 | 19 | + (Foo*)makeFoo:(double)x; 20 | 21 | - (int32_t)multiply:(BOOL)useIntVals withOtherFoo:(Foo*)other; 22 | 23 | - (void)setDoubleVal:(double)x; 24 | 25 | @end 26 | 27 | @implementation Foo 28 | 29 | + (Foo*)makeFoo:(double)x { 30 | Foo* foo = [Foo new]; 31 | foo->doubleVal = x; 32 | [foo setIntVal:((int32_t)x)]; 33 | return foo; 34 | } 35 | 36 | - (int32_t)multiply:(BOOL)useIntVals withOtherFoo:(Foo*)other { 37 | if (useIntVals) { 38 | return [self intVal] * [other intVal]; 39 | } else { 40 | return (int32_t)(self->doubleVal * other->doubleVal); 41 | } 42 | } 43 | 44 | - (void)setDoubleVal:(double)x { 45 | self->doubleVal = x; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_boolean_dartbool_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | class Bindings { 8 | /// Holds the symbol lookup function. 9 | final ffi.Pointer Function(String symbolName) 10 | _lookup; 11 | 12 | /// The symbols are looked up in [dynamicLibrary]. 13 | Bindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; 14 | 15 | /// The symbols are looked up with [lookup]. 16 | Bindings.fromLookup( 17 | ffi.Pointer Function(String symbolName) 18 | lookup) 19 | : _lookup = lookup; 20 | 21 | bool test1( 22 | bool a, 23 | ffi.Pointer b, 24 | ) { 25 | return _test1( 26 | a, 27 | b, 28 | ); 29 | } 30 | 31 | late final _test1Ptr = _lookup< 32 | ffi.NativeFunction< 33 | ffi.Bool Function(ffi.Bool, ffi.Pointer)>>('test1'); 34 | late final _test1 = 35 | _test1Ptr.asFunction)>(); 36 | } 37 | 38 | final class Test2 extends ffi.Struct { 39 | @ffi.Bool() 40 | external bool a; 41 | } 42 | -------------------------------------------------------------------------------- /test/native_objc_test/category_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'category_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late Thing testInstance; 18 | late CategoryTestObjCLibrary lib; 19 | 20 | group('categories', () { 21 | setUpAll(() { 22 | logWarnings(); 23 | final dylib = File('test/native_objc_test/category_test.dylib'); 24 | verifySetupFile(dylib); 25 | lib = CategoryTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 26 | testInstance = Thing.new1(lib); 27 | generateBindingsForCoverage('category'); 28 | }); 29 | 30 | test('Category method', () { 31 | expect(testInstance.add_Y_(1000, 234), 1234); 32 | expect(testInstance.sub_Y_(1234, 1000), 234); 33 | expect(testInstance.mul_Y_(1234, 1000), 1234000); 34 | expect(testInstance.someProperty, 456); 35 | }); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /test/example_tests/libclang_example_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:ffigen/src/code_generator/library.dart'; 8 | import 'package:ffigen/src/config_provider/config.dart'; 9 | import 'package:ffigen/src/header_parser.dart'; 10 | import 'package:logging/logging.dart'; 11 | import 'package:path/path.dart' as path; 12 | import 'package:test/test.dart'; 13 | 14 | import '../test_utils.dart'; 15 | 16 | void main() { 17 | group('example_test', () { 18 | setUpAll(() { 19 | logWarnings(Level.SEVERE); 20 | }); 21 | test('libclang-example', () { 22 | final configYaml = 23 | File(path.join('example', 'libclang-example', 'config.yaml')) 24 | .absolute; 25 | late Config config; 26 | late Library library; 27 | withChDir(configYaml.path, () { 28 | config = testConfigFromPath(configYaml.path); 29 | library = parse(config); 30 | }); 31 | 32 | matchLibraryWithExpected( 33 | library, 34 | 'example_libclang.dart', 35 | [config.output], 36 | ); 37 | }); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /test/header_parser_tests/unions_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('unions_test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Unions Test' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/header_parser_tests/unions.h' 26 | '''), 27 | ); 28 | }); 29 | 30 | test('Expected bindings', () { 31 | matchLibraryWithExpected( 32 | actual, 'header_parser_unions_test_output.dart', [ 33 | 'test', 34 | 'header_parser_tests', 35 | 'expected_bindings', 36 | '_expected_unions_bindings.dart' 37 | ]); 38 | }); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /test/rename_tests/rename.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #define Macro1 1 6 | #define Test_Macro2 2 7 | #define FullMatchMacro3 3 8 | 9 | struct Struct1 10 | { 11 | }; 12 | struct Test_Struct2 13 | { 14 | }; 15 | struct FullMatchStruct3 16 | { 17 | }; 18 | struct MemberRenameStruct4 19 | { 20 | int _underscore; 21 | float fullMatch; 22 | }; 23 | 24 | struct AnyMatchStruct5 25 | { 26 | int _underscore; 27 | }; 28 | 29 | typedef struct Struct5{ 30 | int a; 31 | } Struct5_Alias; 32 | 33 | void func1(struct Struct1 *s); 34 | void test_func2(struct Test_Struct2 *s); 35 | void fullMatch_func3(struct FullMatchStruct3 *s); 36 | void memberRename_func4(int _underscore, float fullMatch, int); 37 | void typedefRenameFunc(Struct5_Alias s); 38 | 39 | enum Enum1 40 | { 41 | a = 0, 42 | b = 1, 43 | c = 2 44 | }; 45 | enum Test_Enum2 46 | { 47 | e = 0, 48 | f = 1, 49 | g = 2 50 | }; 51 | enum FullMatchEnum3 52 | { 53 | i = 0, 54 | j = 1, 55 | k = 2 56 | }; 57 | enum MemberRenameEnum4 58 | { 59 | _underscore = 0, 60 | fullMatch = 1 61 | }; 62 | enum 63 | { 64 | _unnamed_underscore = 0, 65 | unnamedFullMatch = 1 66 | }; 67 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_unions_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | final class Struct1 extends ffi.Struct { 8 | @ffi.Char() 9 | external int a; 10 | } 11 | 12 | final class Union1 extends ffi.Union { 13 | @ffi.Char() 14 | external int a; 15 | } 16 | 17 | final class EmptyUnion extends ffi.Opaque {} 18 | 19 | final class Primitives extends ffi.Union { 20 | @ffi.Char() 21 | external int a; 22 | 23 | @ffi.Int() 24 | external int b; 25 | 26 | @ffi.Float() 27 | external double c; 28 | 29 | @ffi.Double() 30 | external double d; 31 | } 32 | 33 | final class PrimitivesWithPointers extends ffi.Union { 34 | @ffi.Char() 35 | external int a; 36 | 37 | @ffi.Float() 38 | external double b; 39 | 40 | external ffi.Pointer c; 41 | 42 | external ffi.Pointer d; 43 | 44 | external ffi.Pointer d1; 45 | } 46 | 47 | final class WithArray extends ffi.Union { 48 | @ffi.Array.multi([10]) 49 | external ffi.Array a; 50 | 51 | @ffi.Array.multi([10]) 52 | external ffi.Array b; 53 | 54 | @ffi.Array.multi([10]) 55 | external ffi.Array b1; 56 | 57 | @ffi.Array.multi([10]) 58 | external ffi.Array> c; 59 | } 60 | -------------------------------------------------------------------------------- /test/header_parser_tests/forward_decl_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('forward_decl_test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Forward Declaration Test' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/header_parser_tests/forward_decl.h' 26 | '''), 27 | ); 28 | }); 29 | 30 | test('Expected bindings', () { 31 | matchLibraryWithExpected( 32 | actual, 'header_parser_forward_decl_test_output.dart', [ 33 | 'test', 34 | 'header_parser_tests', 35 | 'expected_bindings', 36 | '_expected_forward_decl_bindings.dart' 37 | ]); 38 | }); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /test/header_parser_tests/packed_structs_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('packed_structs_test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Packed Structs Test' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/header_parser_tests/packed_structs.h' 26 | '''), 27 | ); 28 | }); 29 | 30 | test('Expected bindings', () { 31 | matchLibraryWithExpected( 32 | actual, 'header_parser_packed_structs_test_output.dart', [ 33 | 'test', 34 | 'header_parser_tests', 35 | 'expected_bindings', 36 | '_expected_packed_structs_bindings.dart' 37 | ]); 38 | }); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /third_party/cjson_library/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | 22 | Files generated from cJSON source code are 23 | - example/c_json/cjson_generated_bindings.dart 24 | - test/large_integration_tests/_expected_cjson_bindings.dart 25 | -------------------------------------------------------------------------------- /test/config_tests/unknown_keys_warn_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/ffigen.dart'; 6 | import 'package:ffigen/src/strings.dart' as strings; 7 | import 'package:logging/logging.dart'; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | late Library actual, expected; 13 | 14 | void main() { 15 | var logString = ''; 16 | group('unknown_keys_warn_test', () { 17 | setUpAll(() { 18 | final logArr = []; 19 | logWarningsToArray(logArr, Level.WARNING); 20 | testConfig(''' 21 | ${strings.name}: 'NativeLibrary' 22 | ${strings.description}: 'Warn for unknown keys.' 23 | ${strings.output}: 'unused' 24 | ${strings.headers}: 25 | ${strings.entryPoints}: 26 | - 'test/header_parser_tests/packed_structs.h' 27 | 'warn-1': 'warn' 28 | ${strings.typeMap}: 29 | 'warn-2': 'warn' 30 | 'warn-3': 'warn' 31 | '''); 32 | logString = logArr.join("\n"); 33 | }); 34 | test('Warn for unknown keys.', () { 35 | expect(logString.contains('warn-1'), true); 36 | expect(logString.contains('warn-2'), true); 37 | expect(logString.contains('warn-3'), true); 38 | }); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /test/native_objc_test/failed_to_load_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'failed_to_load_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | group('Failed to load', () { 18 | setUpAll(() { 19 | logWarnings(); 20 | generateBindingsForCoverage('failed_to_load'); 21 | }); 22 | 23 | test('Failed to load Objective-C class', () { 24 | // Load from the host executable, which is missing all the classes for 25 | // this test, but has the core ObjC functions, such as objc_getClass. The 26 | // library should load ok, because the classes are lazy loaded. 27 | final lib = FailedToLoadTestObjCLibrary(DynamicLibrary.executable()); 28 | 29 | // But when we try to instantiate one of the classes, we get an error. 30 | expect( 31 | () => ClassThatWillFailToLoad.new1(lib), 32 | throwsA(predicate( 33 | (e) => e.toString().contains('ClassThatWillFailToLoad')))); 34 | }); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /test/header_parser_tests/macros.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define TEST1 1.1 4 | #define TEST2 10 5 | #define TEST3 (TEST1 + TEST2) 6 | #define TEST4 "test" 7 | 8 | // The comma operator should actually return the last value (3), 9 | // when returned by a function. This value, however, when assigned to a variable 10 | // will not compile and so libclang tries to fix it and assigns the first 11 | // value (4) to the generated macro variable. 12 | #define TEST5 4, \ 13 | 2, \ 14 | 3 15 | #define TEST6 (1 == 1); 16 | #define TEST7(x, y) x *y 17 | 18 | #define TEST8 5,2,3 19 | 20 | // These test that special characters are escaped properly. 21 | #define TEST9 "$dollar" 22 | #define TEST10 "test's" 23 | 24 | // These test that extended ASCII and control characters are handled properly. 25 | #define TEST11 "\x80" 26 | #define TEST12 "hello\n\t\r\v\b" 27 | #define TEST13 "test\\" 28 | 29 | // Infinity, NaN and Negative Infinity. 30 | #define TEST14 INFINITY 31 | #define TEST15 -INFINITY 32 | #define TEST16 NAN 33 | 34 | 35 | // Inside include guard. 36 | #ifndef __TEST_INCLUDE_GUARD_1__ 37 | #define __TEST_INCLUDE_GUARD_1__ 38 | 39 | #define TEST17 TEST_FUNCTION_MACRO(0) 40 | #define TEST18 TEST_FUNCTION_MACRO(1) 41 | #define TEST19 TEST_FUNCTION_MACRO(2) 42 | 43 | #define TEST_FUNCTION_MACRO(x) ((unsigned long)((x) << (2))) 44 | 45 | #endif /* __TEST_INCLUDE_GUARD_1__ */ 46 | -------------------------------------------------------------------------------- /test/header_parser_tests/expected_bindings/_expected_forward_decl_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | /// Forward Declaration Test 8 | class NativeLibrary { 9 | /// Holds the symbol lookup function. 10 | final ffi.Pointer Function(String symbolName) 11 | _lookup; 12 | 13 | /// The symbols are looked up in [dynamicLibrary]. 14 | NativeLibrary(ffi.DynamicLibrary dynamicLibrary) 15 | : _lookup = dynamicLibrary.lookup; 16 | 17 | /// The symbols are looked up with [lookup]. 18 | NativeLibrary.fromLookup( 19 | ffi.Pointer Function(String symbolName) 20 | lookup) 21 | : _lookup = lookup; 22 | 23 | void func( 24 | ffi.Pointer a, 25 | int b, 26 | ) { 27 | return _func( 28 | a, 29 | b, 30 | ); 31 | } 32 | 33 | late final _funcPtr = 34 | _lookup, ffi.Int32)>>( 35 | 'func'); 36 | late final _func = _funcPtr.asFunction, int)>(); 37 | } 38 | 39 | final class A extends ffi.Struct { 40 | @ffi.Int() 41 | external int a; 42 | 43 | @ffi.Int() 44 | external int b; 45 | } 46 | 47 | abstract class B { 48 | static const int a = 0; 49 | static const int b = 1; 50 | } 51 | -------------------------------------------------------------------------------- /test/header_parser_tests/unions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | union Union1 6 | { 7 | int a; 8 | }; 9 | 10 | union Union2 11 | { 12 | union Union1 a; 13 | }; 14 | 15 | // Should be marked incomplete, long double not supported. 16 | union Union3 17 | { 18 | long double a; 19 | }; 20 | 21 | // All members should be removed, Bit fields are not supported. 22 | union Union4 23 | { 24 | int a : 3; 25 | int : 2; // Unnamed bit field. 26 | }; 27 | 28 | // All members should be removed, Incomplete union members are not supported. 29 | union Union5 30 | { 31 | int a; 32 | union Union3 s; // Incomplete nested union. 33 | }; 34 | 35 | // Multiple anonymous declarations 36 | union Union6 37 | { 38 | union 39 | { 40 | float a; 41 | }; 42 | 43 | union 44 | { 45 | float b; 46 | }; 47 | }; 48 | 49 | // Multiple anonymous declarations with incomplete members 50 | union Union7 51 | { 52 | union 53 | { 54 | float a; 55 | }; 56 | 57 | union 58 | { 59 | float b; 60 | int c[]; 61 | }; 62 | }; 63 | 64 | void func1(union Union2 *s); 65 | 66 | // Incomplete array parameter will be treated as a pointer. 67 | void func2(union Union3 s[]); 68 | -------------------------------------------------------------------------------- /test/header_parser_tests/function_n_struct.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | struct Struct1 6 | { 7 | int a; 8 | }; 9 | 10 | struct Struct2 11 | { 12 | struct Struct1 a; 13 | }; 14 | 15 | // All members should be removed, Flexible array members are not supported. 16 | struct Struct3 17 | { 18 | int a; 19 | int b[]; // Flexible array member. 20 | }; 21 | 22 | // All members should be removed, Bit fields are not supported. 23 | struct Struct4 24 | { 25 | int a : 3; 26 | int : 2; // Unnamed bit field. 27 | }; 28 | 29 | // All members should be removed, Incomplete struct members are not supported. 30 | struct Struct5 31 | { 32 | int a; 33 | struct Struct3 s; // Incomplete nested struct. 34 | }; 35 | 36 | typedef int arr10[10]; 37 | 38 | struct Struct6 39 | { 40 | arr10 a[2]; 41 | }; 42 | 43 | // All members should be removed, Zero-length arrays are equivalent to 44 | // flexible arrays members (by an extension) are not supported. 45 | struct Struct7 46 | { 47 | int a; 48 | int b[0]; // Flexible array member. 49 | }; 50 | 51 | void func1(struct Struct2 *s); 52 | 53 | // Incomplete array parameter will be treated as a pointer. 54 | void func2(struct Struct3 s[]); 55 | 56 | void func3(arr10 a); 57 | -------------------------------------------------------------------------------- /third_party/libclang/include/clang-c/FatalErrorHandler.h: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/FatalErrorHandler.h - Fatal Error Handling --------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | \*===----------------------------------------------------------------------===*/ 9 | 10 | #ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H 11 | #define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H 12 | 13 | #include "clang-c/ExternC.h" 14 | 15 | LLVM_CLANG_C_EXTERN_C_BEGIN 16 | 17 | /** 18 | * Installs error handler that prints error message to stderr and calls abort(). 19 | * Replaces currently installed error handler (if any). 20 | */ 21 | void clang_install_aborting_llvm_fatal_error_handler(void); 22 | 23 | /** 24 | * Removes currently installed error handler (if any). 25 | * If no error handler is intalled, the default strategy is to print error 26 | * message to stderr and call exit(1). 27 | */ 28 | void clang_uninstall_llvm_fatal_error_handler(void); 29 | 30 | LLVM_CLANG_C_EXTERN_C_END 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /test/header_parser_tests/regress_384_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('regress_384_test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Regression test for #384' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/header_parser_tests/regress_384_header_1.h' 26 | - 'test/header_parser_tests/regress_384_header_2.h' 27 | '''), 28 | ); 29 | }); 30 | 31 | test('Expected bindings', () { 32 | matchLibraryWithExpected( 33 | actual, 'header_parser_regress_384_test_output.dart', [ 34 | 'test', 35 | 'header_parser_tests', 36 | 'expected_bindings', 37 | '_expected_regress_384_bindings.dart' 38 | ]); 39 | }); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/code_generator/dart_keywords.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /// Dart reserved keywords, used for resolving conflict with a name. 6 | /// 7 | /// Source: https://dart.dev/guides/language/language-tour#keywords. 8 | const keywords = { 9 | 'abstract', 10 | 'as', 11 | 'assert', 12 | 'async', 13 | 'await', 14 | 'break', 15 | 'case', 16 | 'catch', 17 | 'class', 18 | 'const', 19 | 'continue', 20 | 'covariant', 21 | 'default', 22 | 'deferred', 23 | 'do', 24 | 'dynamic', 25 | 'else', 26 | 'enum', 27 | 'export', 28 | 'extends', 29 | 'extension', 30 | 'external', 31 | 'factory', 32 | 'false', 33 | 'final', 34 | 'finally', 35 | 'for', 36 | 'Function', 37 | 'get', 38 | 'hide', 39 | 'if', 40 | 'implements', 41 | 'import', 42 | 'in', 43 | 'interface', 44 | 'is', 45 | 'late', 46 | 'library', 47 | 'mixin', 48 | 'new', 49 | 'null', 50 | 'on', 51 | 'operator', 52 | 'part', 53 | 'required', 54 | 'rethrow', 55 | 'return', 56 | 'set', 57 | 'show', 58 | 'static', 59 | 'super', 60 | 'switch', 61 | 'sync', 62 | 'this', 63 | 'throw', 64 | 'true', 65 | 'try', 66 | 'typedef', 67 | 'var', 68 | 'void', 69 | 'while', 70 | 'with', 71 | 'yield', 72 | }; 73 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_function_n_struct_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | class Bindings { 8 | /// Holds the symbol lookup function. 9 | final ffi.Pointer Function(String symbolName) 10 | _lookup; 11 | 12 | /// The symbols are looked up in [dynamicLibrary]. 13 | Bindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; 14 | 15 | /// The symbols are looked up with [lookup]. 16 | Bindings.fromLookup( 17 | ffi.Pointer Function(String symbolName) 18 | lookup) 19 | : _lookup = lookup; 20 | 21 | ffi.Pointer someFunc( 22 | ffi.Pointer> some, 23 | ) { 24 | return _someFunc( 25 | some, 26 | ); 27 | } 28 | 29 | late final _someFuncPtr = _lookup< 30 | ffi.NativeFunction< 31 | ffi.Pointer Function( 32 | ffi.Pointer>)>>('someFunc'); 33 | late final _someFunc = _someFuncPtr.asFunction< 34 | ffi.Pointer Function(ffi.Pointer>)>(); 35 | } 36 | 37 | final class SomeStruct extends ffi.Struct { 38 | @ffi.Int32() 39 | external int a; 40 | 41 | @ffi.Double() 42 | external double b; 43 | 44 | @ffi.Uint8() 45 | external int c; 46 | } 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Process 26 | 27 | Some of our branching and releasing process is described on the 28 | [wiki](https://github.com/dart-lang/ffigen/wiki). Please familiarize yourself 29 | with the info there. 30 | 31 | ## Community Guidelines 32 | 33 | This project follows [Google's Open Source Community 34 | Guidelines](https://opensource.google/conduct/) and the [Dart code of 35 | conduct](https://dart.dev/code-of-conduct). 36 | -------------------------------------------------------------------------------- /test/header_parser_tests/comment_markup_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('comment_markup_test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Comment Markup Test' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/header_parser_tests/comment_markup.h' 26 | ${strings.comments}: 27 | ${strings.style}: ${strings.any} 28 | ${strings.length}: ${strings.full} 29 | '''), 30 | ); 31 | }); 32 | 33 | test('Expected bindings', () { 34 | matchLibraryWithExpected( 35 | actual, 'header_parser_comment_markup_test_output.dart', [ 36 | 'test', 37 | 'header_parser_tests', 38 | 'expected_bindings', 39 | '_expected_comment_markup_bindings.dart' 40 | ]); 41 | }); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /test/header_parser_tests/imported_types_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | late Library actual, expected; 13 | 14 | void main() { 15 | group('imported_types_test', () { 16 | setUpAll(() { 17 | logWarnings(); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Imported types test' 22 | ${strings.output}: 'unused' 23 | 24 | ${strings.headers}: 25 | ${strings.entryPoints}: 26 | - 'test/header_parser_tests/imported_types.h' 27 | ${strings.includeDirectives}: 28 | - '**imported_types.h' 29 | 30 | ${strings.preamble}: | 31 | // ignore_for_file: camel_case_types 32 | '''), 33 | ); 34 | }); 35 | test('Expected Bindings', () { 36 | matchLibraryWithExpected( 37 | actual, 'header_parser_imported_types_test_output.dart', [ 38 | 'test', 39 | 'header_parser_tests', 40 | 'expected_bindings', 41 | '_expected_imported_types_bindings.dart' 42 | ]); 43 | }); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /test/native_objc_test/util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef _TEST_UTIL_H_ 6 | #define _TEST_UTIL_H_ 7 | 8 | typedef struct { 9 | void* isa; 10 | int flags; 11 | // There are other fields, but we just need the flags and isa. 12 | } BlockRefCountExtractor; 13 | 14 | static void* valid_block_isa = NULL; 15 | uint64_t getBlockRetainCount(void* block) { 16 | BlockRefCountExtractor* b = (BlockRefCountExtractor*)block; 17 | // HACK: The only way I can find to reliably figure out that a block has been 18 | // deleted is to check the isa field (the lower bits of the flags field seem 19 | // to be randomized, not just set to 0). But we also don't know the value this 20 | // field has when it's constructed (copying the block changes it from 21 | // _NSConcreteGlobalBlock to an internal value). So we assume that the first 22 | // time this function is called, we have a valid block, and on subsequent 23 | // calls we check to see if the isa field changed. 24 | if (valid_block_isa == NULL) { 25 | valid_block_isa = b->isa; 26 | } 27 | if (b->isa != valid_block_isa) { 28 | return 0; 29 | } 30 | // The ref count is stored in the lower bits of the flags field, but skips the 31 | // 0x1 bit. 32 | return (b->flags & 0xFFFF) >> 1; 33 | } 34 | 35 | #endif // _TEST_UTIL_H_ 36 | -------------------------------------------------------------------------------- /test/collision_tests/decl_type_name_collision_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('decl_type_name_collision test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Decl type name collision test' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/collision_tests/decl_type_name_collision.h' 26 | ${strings.preamble}: | 27 | // ignore_for_file: non_constant_identifier_names, 28 | '''), 29 | ); 30 | }); 31 | 32 | test('Expected bindings', () { 33 | matchLibraryWithExpected( 34 | actual, 'decl_type_name_collision_test_output.dart', [ 35 | 'test', 36 | 'collision_tests', 37 | 'expected_bindings', 38 | '_expected_decl_type_name_collision_bindings.dart' 39 | ]); 40 | }); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /test/header_parser_tests/dart_handle_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:cli_util/cli_util.dart'; 6 | import 'package:ffigen/src/code_generator.dart'; 7 | import 'package:ffigen/src/header_parser.dart' as parser; 8 | import 'package:ffigen/src/strings.dart' as strings; 9 | import 'package:path/path.dart' as path; 10 | import 'package:test/test.dart'; 11 | 12 | import '../test_utils.dart'; 13 | 14 | late Library actual, expected; 15 | 16 | void main() { 17 | group('dart_handle_test', () { 18 | setUpAll(() { 19 | logWarnings(); 20 | actual = parser.parse( 21 | testConfig(''' 22 | ${strings.name}: 'NativeLibrary' 23 | ${strings.description}: 'Dart_Handle Test' 24 | ${strings.output}: 'unused' 25 | ${strings.compilerOpts}: '-I${path.join(getSdkPath(), "include")}' 26 | 27 | ${strings.headers}: 28 | ${strings.entryPoints}: 29 | - 'test/header_parser_tests/dart_handle.h' 30 | ${strings.includeDirectives}: 31 | - '**dart_handle.h' 32 | '''), 33 | ); 34 | }); 35 | test('Expected Bindings', () { 36 | matchLibraryWithExpected( 37 | actual, 'header_parser_dart_handle_test_output.dart', [ 38 | 'test', 39 | 'header_parser_tests', 40 | 'expected_bindings', 41 | '_expected_dart_handle_bindings.dart' 42 | ]); 43 | }); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /test/native_objc_test/bad_method_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'bad_method_test_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late NativeObjCLibrary lib; 18 | group('bad_method_test', () { 19 | setUpAll(() { 20 | logWarnings(); 21 | final dylib = File('test/native_objc_test/bad_method_test.dylib'); 22 | verifySetupFile(dylib); 23 | lib = NativeObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 24 | generateBindingsForCoverage('bad_method'); 25 | }); 26 | 27 | test("Test incomplete struct methods that weren't skipped", () { 28 | final obj = BadMethodTestObject.new1(lib); 29 | final structPtr = obj.incompletePointerReturn(); 30 | expect(structPtr.address, 1234); 31 | expect(obj.incompletePointerParam_(structPtr), 1234); 32 | }); 33 | 34 | test("Test bit field methods that weren't skipped", () { 35 | final obj = BadMethodTestObject.new1(lib); 36 | final bitFieldPtr = obj.bitFieldPointerReturn(); 37 | expect(bitFieldPtr.address, 5678); 38 | expect(obj.bitFieldPointerParam_(bitFieldPtr), 5678); 39 | }); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /test/config_tests/compiler_opts_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/ffigen.dart'; 6 | import 'package:ffigen/src/config_provider/spec_utils.dart'; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | late Library actual, expected; 13 | 14 | void main() { 15 | group('compiler_opts_test', () { 16 | test('Compiler Opts', () { 17 | final opts = 18 | '''--option value "in double quotes" 'in single quotes' -tab=separated'''; 19 | final list = compilerOptsToList(opts); 20 | expect( 21 | list, 22 | [ 23 | '--option', 24 | 'value', 25 | 'in double quotes', 26 | 'in single quotes', 27 | '-tab=separated', 28 | ], 29 | ); 30 | }); 31 | test('Compiler Opts Automatic', () { 32 | final config = testConfig(''' 33 | ${strings.name}: 'NativeLibrary' 34 | ${strings.description}: 'Compiler Opts Test' 35 | ${strings.output}: 'unused' 36 | ${strings.headers}: 37 | ${strings.entryPoints}: 38 | - 'test/header_parser_tests/comment_markup.h' 39 | ${strings.compilerOptsAuto}: 40 | ${strings.macos}: 41 | ${strings.includeCStdLib}: false 42 | '''); 43 | expect(config.compilerOpts.isEmpty, true); 44 | }); 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/header_parser/sub_parsers/objc_block_parser.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser/data.dart'; 7 | import 'package:logging/logging.dart'; 8 | 9 | import '../clang_bindings/clang_bindings.dart' as clang_types; 10 | import '../utils.dart'; 11 | 12 | final _logger = Logger('ffigen.header_parser.objc_block_parser'); 13 | 14 | ObjCBlock parseObjCBlock(clang_types.CXType cxtype) { 15 | final blk = clang.clang_getPointeeType(cxtype); 16 | final returnType = clang.clang_getResultType(blk).toCodeGenType(); 17 | final argTypes = []; 18 | final int numArgs = clang.clang_getNumArgTypes(blk); 19 | for (int i = 0; i < numArgs; ++i) { 20 | argTypes.add(clang.clang_getArgType(blk, i).toCodeGenType()); 21 | } 22 | 23 | // Create a fake USR code for the block. This code is used to dedupe blocks 24 | // with the same signature. 25 | var usr = 'objcBlock: ${returnType.cacheKey()}'; 26 | for (final type in argTypes) { 27 | usr += ' ${type.cacheKey()}'; 28 | } 29 | 30 | _logger.fine('++++ Adding ObjC block: ' 31 | '${cxtype.completeStringRepr()}, syntheticUsr: $usr'); 32 | 33 | return ObjCBlock( 34 | usr: usr.toString(), 35 | returnType: returnType, 36 | argTypes: argTypes, 37 | builtInFunctions: objCBuiltInFunctions, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /test/header_parser_tests/struct_fptr_fields_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/config_provider.dart'; 7 | import 'package:ffigen/src/header_parser.dart' as parser; 8 | import 'package:ffigen/src/strings.dart' as strings; 9 | import 'package:logging/logging.dart'; 10 | import 'package:test/test.dart'; 11 | import 'package:yaml/yaml.dart' as yaml; 12 | 13 | import '../test_utils.dart'; 14 | 15 | late Library actual; 16 | void main() { 17 | group('Function pointer parameters parsing test', () { 18 | setUpAll(() { 19 | logWarnings(Level.SEVERE); 20 | actual = parser.parse( 21 | Config.fromYaml(yaml.loadYaml(''' 22 | ${strings.name}: 'NativeLibrary' 23 | ${strings.description}: 'Function pointer fields in structs Test' 24 | ${strings.output}: 'unused' 25 | ${strings.headers}: 26 | ${strings.entryPoints}: 27 | - 'test/header_parser_tests/struct_fptr_fields.h' 28 | ''') as yaml.YamlMap), 29 | ); 30 | }); 31 | 32 | test('Expected bindings', () { 33 | matchLibraryWithExpected( 34 | actual, 'header_parser_struct_fptr_fields_output.dart', [ 35 | 'test', 36 | 'header_parser_tests', 37 | 'expected_bindings', 38 | '_expected_struct_fptr_fields_bindings.dart', 39 | ]); 40 | }); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /test/native_objc_test/bad_method_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | struct IncompleteStruct; 8 | 9 | struct BitField { 10 | int x:3; 11 | int y:12; 12 | }; 13 | 14 | @interface BadMethodTestObject : NSObject { 15 | } 16 | 17 | - (struct IncompleteStruct)incompleteReturn; // Skipped. 18 | - (struct IncompleteStruct*)incompletePointerReturn; // Not skipped. 19 | - (int64_t)incompleteParam:(struct IncompleteStruct)x; // Skipped. 20 | - (int64_t)incompletePointerParam:(struct IncompleteStruct*)x; // Not skipped. 21 | 22 | - (struct BitField)bitFieldReturn; // Skipped. 23 | - (struct BitField*)bitFieldPointerReturn; // Not skipped. 24 | - (int64_t)bitFieldParam:(struct BitField)x; // Skipped. 25 | - (int64_t)bitFieldPointerParam:(struct BitField*)x; // Not skipped. 26 | 27 | @property struct BitField bitFieldProperty; // Skipped. 28 | 29 | @end 30 | 31 | @implementation BadMethodTestObject 32 | 33 | - (struct IncompleteStruct*)incompletePointerReturn { 34 | return (struct IncompleteStruct*)1234; 35 | } 36 | 37 | - (int64_t)incompletePointerParam:(struct IncompleteStruct*)x { 38 | return (int64_t)x; 39 | } 40 | 41 | - (struct BitField*)bitFieldPointerReturn { 42 | return (struct BitField*)5678; 43 | } 44 | 45 | - (int64_t)bitFieldPointerParam:(struct BitField*)x { 46 | return (int64_t)x; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /test/native_objc_test/nullable_inheritance_test.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NullableBase : NSObject {} 4 | 5 | -(BOOL) nullableArg:(nullable NSObject *)x; 6 | -(BOOL) nonNullArg:(NSObject *)x; 7 | -(nullable NSObject *) nullableReturn:(BOOL)r; 8 | -(NSObject*) nonNullReturn; 9 | 10 | @end 11 | 12 | @implementation NullableBase 13 | 14 | -(BOOL) nullableArg:(nullable NSObject *)x { 15 | return x == NULL; 16 | } 17 | 18 | -(BOOL) nonNullArg:(NSObject *)x { 19 | return x == NULL; 20 | } 21 | 22 | -(nullable NSObject *) nullableReturn:(BOOL)r { 23 | if (r) { 24 | return nil; 25 | } else { 26 | return [NSObject new]; 27 | } 28 | } 29 | 30 | -(NSObject *) nonNullReturn { 31 | return [NSObject new]; 32 | } 33 | 34 | @end 35 | 36 | @interface NullableIntermediate : NullableBase {} 37 | @end 38 | @implementation NullableIntermediate 39 | @end 40 | 41 | @interface NullableChild : NullableIntermediate {} 42 | 43 | // Redeclare the same methods with different nullability. 44 | -(BOOL) nullableArg:(NSObject *)x; 45 | -(BOOL) nonNullArg:(nullable NSObject *)x; 46 | -(NSObject *) nullableReturn:(BOOL)r; 47 | -(nullable NSObject *) nonNullReturn; 48 | 49 | @end 50 | 51 | @implementation NullableChild 52 | 53 | -(BOOL) nullableArg:(NSObject *)x { 54 | return x == NULL; 55 | } 56 | 57 | -(BOOL) nonNullArg:(nullable NSObject *)x { 58 | return x == NULL; 59 | } 60 | 61 | -(NSObject *) nullableReturn:(BOOL)r { 62 | return [NSObject new]; 63 | } 64 | 65 | -(nullable NSObject *) nonNullReturn { 66 | return nil; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /test/example_tests/shared_bindings_example_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/header_parser.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:path/path.dart' as path; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | void main() { 13 | group('shared_bindings_example', () { 14 | setUpAll(() { 15 | logWarnings(Level.SEVERE); 16 | }); 17 | 18 | test('a_shared_base bindings', () { 19 | final config = testConfigFromPath(path.join( 20 | 'example', 21 | 'shared_bindings', 22 | 'ffigen_configs', 23 | 'a_shared_base.yaml', 24 | )); 25 | final library = parse(config); 26 | 27 | matchLibraryWithExpected( 28 | library, 29 | 'example_shared_bindings.dart', 30 | [config.output], 31 | ); 32 | }); 33 | 34 | test('base symbol file output', () { 35 | final config = testConfigFromPath(path.join( 36 | 'example', 37 | 'shared_bindings', 38 | 'ffigen_configs', 39 | 'base.yaml', 40 | )); 41 | final library = parse(config); 42 | matchLibrarySymbolFileWithExpected( 43 | library, 44 | 'example_shared_bindings.yaml', 45 | [config.symbolFile!.output], 46 | config.symbolFile!.importPath, 47 | ); 48 | }); 49 | }); 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/header_parser/type_extractor/cxtypekindmap.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart' show SupportedNativeType; 6 | import 'package:ffigen/src/code_generator/imports.dart'; 7 | 8 | var cxTypeKindToImportedTypes = { 9 | 'void': voidType, 10 | 'unsigned char': unsignedCharType, 11 | 'signed char': signedCharType, 12 | 'char': charType, 13 | 'unsigned short': unsignedShortType, 14 | 'short': shortType, 15 | 'unsigned int': unsignedIntType, 16 | 'int': intType, 17 | 'unsigned long': unsignedLongType, 18 | 'long': longType, 19 | 'unsigned long long': unsignedLongLongType, 20 | 'long long': longLongType, 21 | 'float': floatType, 22 | 'double': doubleType, 23 | }; 24 | 25 | var suportedTypedefToSuportedNativeType = { 26 | 'uint8_t': SupportedNativeType.Uint8, 27 | 'uint16_t': SupportedNativeType.Uint16, 28 | 'uint32_t': SupportedNativeType.Uint32, 29 | 'uint64_t': SupportedNativeType.Uint64, 30 | 'int8_t': SupportedNativeType.Int8, 31 | 'int16_t': SupportedNativeType.Int16, 32 | 'int32_t': SupportedNativeType.Int32, 33 | 'int64_t': SupportedNativeType.Int64, 34 | 'intptr_t': SupportedNativeType.IntPtr, 35 | 'uintptr_t': SupportedNativeType.UintPtr, 36 | }; 37 | 38 | var supportedTypedefToImportedType = { 39 | 'size_t': sizeType, 40 | 'wchar_t': wCharType, 41 | }; 42 | -------------------------------------------------------------------------------- /test/header_parser_tests/native_func_typedef_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('native_func_typedef_test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Native Func Typedef Test.' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/header_parser_tests/native_func_typedef.h' 26 | '''), 27 | ); 28 | }); 29 | 30 | test('Remove deeply nested unsupported types', () { 31 | expect(() => actual.getBindingAsString('funcNestedUnimplemented'), 32 | throwsA(TypeMatcher())); 33 | }); 34 | 35 | test('Expected bindings', () { 36 | matchLibraryWithExpected( 37 | actual, 'header_parser_native_func_typedef_test_output.dart', [ 38 | 'test', 39 | 'header_parser_tests', 40 | 'expected_bindings', 41 | '_expected_native_func_typedef_bindings.dart' 42 | ]); 43 | }); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /example/ffinative/lib/generated_bindings.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: deprecated_member_use 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | import 'dart:ffi' as ffi; 8 | 9 | /// Adds 2 integers. 10 | @ffi.Native( 11 | symbol: 'sum', assetId: 'package:ffinative_example/generated_bindings.dart') 12 | external int sum( 13 | int a, 14 | int b, 15 | ); 16 | 17 | /// Subtracts 2 integers. 18 | @ffi.Native( 19 | symbol: 'subtract', 20 | assetId: 'package:ffinative_example/generated_bindings.dart') 21 | external int subtract( 22 | int a, 23 | int b, 24 | ); 25 | 26 | /// Multiplies 2 integers, returns pointer to an integer,. 27 | @ffi.Native Function(ffi.Int, ffi.Int)>( 28 | symbol: 'multiply', 29 | assetId: 'package:ffinative_example/generated_bindings.dart') 30 | external ffi.Pointer multiply( 31 | int a, 32 | int b, 33 | ); 34 | 35 | /// Divides 2 integers, returns pointer to a float. 36 | @ffi.Native Function(ffi.Int, ffi.Int)>( 37 | symbol: 'divide', 38 | assetId: 'package:ffinative_example/generated_bindings.dart') 39 | external ffi.Pointer divide( 40 | int a, 41 | int b, 42 | ); 43 | 44 | /// Divides 2 floats, returns a pointer to double. 45 | @ffi.Native Function(ffi.Float, ffi.Float)>( 46 | symbol: 'dividePrecision', 47 | assetId: 'package:ffinative_example/generated_bindings.dart') 48 | external ffi.Pointer dividePrecision( 49 | double a, 50 | double b, 51 | ); 52 | -------------------------------------------------------------------------------- /lib/src/code_generator/constant.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'binding.dart'; 6 | import 'binding_string.dart'; 7 | import 'utils.dart'; 8 | import 'writer.dart'; 9 | 10 | /// A simple Constant. 11 | /// 12 | /// Expands to - 13 | /// ```dart 14 | /// const = ; 15 | /// ``` 16 | /// 17 | /// Example - 18 | /// ```dart 19 | /// const int name = 10; 20 | /// ``` 21 | class Constant extends NoLookUpBinding { 22 | /// The rawType is pasted as it is. E.g 'int', 'String', 'double' 23 | final String rawType; 24 | 25 | /// The rawValue is pasted as it is. 26 | /// 27 | /// Put quotes if type is a string. 28 | final String rawValue; 29 | 30 | Constant({ 31 | super.usr, 32 | super.originalName, 33 | required super.name, 34 | super.dartDoc, 35 | required this.rawType, 36 | required this.rawValue, 37 | }); 38 | 39 | @override 40 | BindingString toBindingString(Writer w) { 41 | final s = StringBuffer(); 42 | final constantName = name; 43 | 44 | if (dartDoc != null) { 45 | s.write(makeDartDoc(dartDoc!)); 46 | } 47 | 48 | s.write('\nconst $rawType $constantName = $rawValue;\n\n'); 49 | 50 | return BindingString( 51 | type: BindingStringType.constant, string: s.toString()); 52 | } 53 | 54 | @override 55 | void addDependencies(Set dependencies) { 56 | if (dependencies.contains(this)) return; 57 | 58 | dependencies.add(this); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/header_parser_tests/functions_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | late Library actual, expected; 13 | 14 | void main() { 15 | group('functions_test', () { 16 | setUpAll(() { 17 | logWarnings(); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Functions Test' 22 | ${strings.output}: 'unused' 23 | 24 | ${strings.headers}: 25 | ${strings.entryPoints}: 26 | - 'test/header_parser_tests/functions.h' 27 | ${strings.includeDirectives}: 28 | - '**functions.h' 29 | 30 | ${strings.functions}: 31 | ${strings.symbolAddress}: 32 | ${strings.include}: 33 | - func3 34 | - func4 35 | ${strings.leafFunctions}: 36 | ${strings.include}: 37 | - func1 38 | 39 | ${strings.preamble}: | 40 | // ignore_for_file: camel_case_types 41 | '''), 42 | ); 43 | }); 44 | test('Expected Bindings', () { 45 | matchLibraryWithExpected( 46 | actual, 'header_parser_functions_test_output.dart', [ 47 | 'test', 48 | 'header_parser_tests', 49 | 'expected_bindings', 50 | '_expected_functions_bindings.dart' 51 | ]); 52 | }); 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /example/c_json/config.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../ffigen.schema.json 2 | 3 | output: 'cjson_generated_bindings.dart' 4 | name: 'CJson' 5 | description: 'Holds bindings to cJSON.' 6 | headers: 7 | entry-points: 8 | - '../../third_party/cjson_library/cJSON.h' 9 | include-directives: 10 | - '**cJSON.h' 11 | comments: false 12 | preamble: | 13 | // Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 14 | // 15 | // Permission is hereby granted, free of charge, to any person obtaining a copy 16 | // of this software and associated documentation files (the "Software"), to deal 17 | // in the Software without restriction, including without limitation the rights 18 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | // copies of the Software, and to permit persons to whom the Software is 20 | // furnished to do so, subject to the following conditions: 21 | // 22 | // The above copyright notice and this permission notice shall be included in 23 | // all copies or substantial portions of the Software. 24 | // 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 | // THE SOFTWARE. 32 | 33 | // ignore_for_file: camel_case_types, non_constant_identifier_names -------------------------------------------------------------------------------- /test/header_parser_tests/opaque_dependencies_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual; 14 | void main() { 15 | group('opaque_dependencies_test', () { 16 | setUpAll(() { 17 | logWarnings(Level.SEVERE); 18 | actual = parser.parse( 19 | testConfig(''' 20 | ${strings.name}: 'NativeLibrary' 21 | ${strings.description}: 'Opaque Dependencies Test' 22 | ${strings.output}: 'unused' 23 | ${strings.headers}: 24 | ${strings.entryPoints}: 25 | - 'test/header_parser_tests/opaque_dependencies.h' 26 | ${strings.structs}: 27 | ${strings.include}: 28 | - 'E' 29 | ${strings.dependencyOnly}: ${strings.opaqueCompoundDependencies} 30 | ${strings.unions}: 31 | ${strings.include}: 32 | - 'UE' 33 | ${strings.dependencyOnly}: ${strings.opaqueCompoundDependencies} 34 | '''), 35 | ); 36 | }); 37 | test('Expected bindings', () { 38 | matchLibraryWithExpected( 39 | actual, 'header_parser_opaque_dependencies_test_output.dart', [ 40 | 'test', 41 | 'header_parser_tests', 42 | 'expected_bindings', 43 | '_expected_opaque_dependencies_bindings.dart' 44 | ]); 45 | }); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /test/native_objc_test/method_test.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | typedef struct { 4 | double x; 5 | double y; 6 | double z; 7 | double w; 8 | } Vec4; 9 | 10 | @interface MethodInterface : NSObject { 11 | } 12 | 13 | 14 | -(int32_t)add; 15 | -(int32_t)add:(int32_t)x; 16 | -(int32_t)add:(int32_t)x Y:(int32_t) y; 17 | -(int32_t)add:(int32_t)x Y:(int32_t) y Z:(int32_t) z; 18 | 19 | +(int32_t)sub; 20 | +(int32_t)sub:(int32_t)x; 21 | +(int32_t)sub:(int32_t)x Y:(int32_t) y; 22 | +(int32_t)sub:(int32_t)x Y:(int32_t) y Z:(int32_t) z; 23 | 24 | -(Vec4)twiddleVec4Components:(Vec4)v; 25 | -(float)addFloats:(float)x Y:(float) y; 26 | -(double)addDoubles:(double)x Y:(double) y; 27 | 28 | @end 29 | 30 | @implementation MethodInterface 31 | 32 | -(int32_t)add { 33 | return 5; 34 | } 35 | 36 | -(int32_t)add:(int32_t)x { 37 | return x; 38 | } 39 | 40 | -(int32_t)add:(int32_t)x Y:(int32_t) y { 41 | return x + y; 42 | } 43 | 44 | -(int32_t)add:(int32_t)x Y:(int32_t) y Z:(int32_t) z { 45 | return x + y + z; 46 | } 47 | 48 | +(int32_t)sub { 49 | return -5; 50 | } 51 | 52 | +(int32_t)sub:(int32_t)x { 53 | return -x; 54 | } 55 | 56 | +(int32_t)sub:(int32_t)x Y:(int32_t) y { 57 | return -x - y; 58 | } 59 | 60 | +(int32_t)sub:(int32_t)x Y:(int32_t) y Z:(int32_t) z { 61 | return - x - y - z; 62 | } 63 | 64 | -(Vec4)twiddleVec4Components:(Vec4)v { 65 | Vec4 u; 66 | u.x = v.y; 67 | u.y = v.z; 68 | u.z = v.w; 69 | u.w = v.x; 70 | return u; 71 | } 72 | 73 | -(float)addFloats:(float)x Y:(float) y { 74 | return x + y; 75 | } 76 | 77 | -(double)addDoubles:(double)x Y:(double) y { 78 | return x + y; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | Code generated by FFIgen is owned by the owner of the input file used 30 | when generating it. 31 | -------------------------------------------------------------------------------- /example/objective_c/README.md: -------------------------------------------------------------------------------- 1 | # Objective C example 2 | 3 | This example shows how to use ffigen to generate bindings for an Objective C 4 | library. It uses the AVFAudio framework to play audio files. 5 | 6 | ``` 7 | dart play_audio.dart test.mp3 8 | ``` 9 | 10 | ## Config notes 11 | 12 | The ffigen config for an Objective C library looks very similar to a C library. 13 | The most important difference is that you must set `language: objc`. If you want 14 | to filter which interfaces are included you can use the `objc-interfaces:` 15 | option. This works similarly to the other filtering options. 16 | 17 | It is recommended that you filter out just about everything you're not 18 | interested in binding (see the ffigen config in [pubspec.yaml](./pubspec.yaml)). 19 | Virtually all Objective C libraries depend on Apple's internal libraries, which 20 | are huge. Filtering can reduce the generated bindings from millions of lines to 21 | tens of thousands. You can use the `exclude-all-by-default` flag, or exclude 22 | individual sets of declarations like this: 23 | 24 | ```yaml 25 | functions: 26 | exclude: 27 | - '.*' 28 | # Same for structs/unions/enums etc. 29 | ``` 30 | 31 | In this example, we're only interested in `AVAudioPlayer`, so we've filtered out 32 | everything else. But ffigen will automatically pull in anything referenced by 33 | any of the fields or methods of `AVAudioPlayer`, so we're still able to use 34 | `NSURL` etc to load our audio file. 35 | 36 | ## Generating bindings 37 | 38 | At the root of this example (`example/objective_c`), run: 39 | 40 | ``` 41 | dart run ffigen --config config.yaml 42 | ``` 43 | 44 | This will generate [avf_audio_bindings.dart](./avf_audio_bindings.dart). 45 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_global_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | class Bindings { 8 | /// Holds the symbol lookup function. 9 | final ffi.Pointer Function(String symbolName) 10 | _lookup; 11 | 12 | /// The symbols are looked up in [dynamicLibrary]. 13 | Bindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; 14 | 15 | /// The symbols are looked up with [lookup]. 16 | Bindings.fromLookup( 17 | ffi.Pointer Function(String symbolName) 18 | lookup) 19 | : _lookup = lookup; 20 | 21 | late final ffi.Pointer _test1 = _lookup('test1'); 22 | 23 | int get test1 => _test1.value; 24 | 25 | set test1(int value) => _test1.value = value; 26 | 27 | late final ffi.Pointer> _test2 = 28 | _lookup>('test2'); 29 | 30 | ffi.Pointer get test2 => _test2.value; 31 | 32 | set test2(ffi.Pointer value) => _test2.value = value; 33 | 34 | late final ffi.Pointer> _test5 = 35 | _lookup>('test5'); 36 | 37 | ffi.Pointer get test5 => _test5.value; 38 | 39 | set test5(ffi.Pointer value) => _test5.value = value; 40 | 41 | late final ffi.Pointer _globalStruct = 42 | _lookup('globalStruct'); 43 | 44 | ffi.Pointer get globalStruct => _globalStruct; 45 | } 46 | 47 | final class Some extends ffi.Opaque {} 48 | 49 | final class EmptyStruct extends ffi.Opaque {} 50 | -------------------------------------------------------------------------------- /test/header_parser_tests/separate_definition_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/config_provider.dart'; 7 | import 'package:ffigen/src/header_parser.dart' as parser; 8 | import 'package:ffigen/src/strings.dart' as strings; 9 | import 'package:logging/logging.dart'; 10 | import 'package:test/test.dart'; 11 | 12 | import '../test_utils.dart'; 13 | 14 | late Library actual, expected; 15 | 16 | void main() { 17 | group('separate_definition', () { 18 | setUpAll(() { 19 | logWarnings(Level.SEVERE); 20 | }); 21 | test('different header order', () { 22 | final entryPoints = [ 23 | "test/header_parser_tests/separate_definition_base.h", 24 | "test/header_parser_tests/separate_definition.h" 25 | ]; 26 | final library1String = parser.parse(_makeConfig(entryPoints)).generate(); 27 | final library2String = 28 | parser.parse(_makeConfig(entryPoints.reversed.toList())).generate(); 29 | 30 | expect(library1String, library2String); 31 | }); 32 | }); 33 | } 34 | 35 | Config _makeConfig(List entryPoints) { 36 | final entryPointBuilder = StringBuffer(); 37 | for (final ep in entryPoints) { 38 | entryPointBuilder.writeln(" - $ep"); 39 | } 40 | final config = testConfig(''' 41 | ${strings.name}: 'Bindings' 42 | ${strings.output}: 'unused' 43 | 44 | ${strings.headers}: 45 | ${strings.entryPoints}: 46 | ${entryPointBuilder.toString()} 47 | '''); 48 | return config; 49 | } 50 | -------------------------------------------------------------------------------- /test/native_objc_test/string_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'string_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late StringTestObjCLibrary lib; 18 | 19 | group('string', () { 20 | setUpAll(() { 21 | logWarnings(); 22 | final dylib = File('test/native_objc_test/string_test.dylib'); 23 | verifySetupFile(dylib); 24 | lib = StringTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 25 | generateBindingsForCoverage('string'); 26 | }); 27 | 28 | for (final s in ['Hello', '🇵🇬', 'Embedded\u0000Null']) { 29 | test('NSString to/from Dart string [$s]', () { 30 | final ns1 = NSString(lib, s); 31 | expect(ns1.length, s.length); 32 | expect(ns1.toString().length, s.length); 33 | expect(ns1.toString(), s); 34 | 35 | final ns2 = s.toNSString(lib); 36 | expect(ns2.length, s.length); 37 | expect(ns2.toString().length, s.length); 38 | expect(ns2.toString(), s); 39 | }); 40 | } 41 | 42 | test('strings usable', () { 43 | final str1 = 'Hello'.toNSString(lib); 44 | final str2 = 'World!'.toNSString(lib); 45 | 46 | final str3 = StringUtil.strConcat_with_(lib, str1, str2); 47 | expect(str3.length, 11); 48 | expect(str3.toString(), "HelloWorld!"); 49 | }); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /third_party/libclang/include/clang-c/Platform.h: -------------------------------------------------------------------------------- 1 | /*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This header provides platform specific macros (dllimport, deprecated, ...) *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | #ifndef LLVM_CLANG_C_PLATFORM_H 15 | #define LLVM_CLANG_C_PLATFORM_H 16 | 17 | #include "clang-c/ExternC.h" 18 | 19 | LLVM_CLANG_C_EXTERN_C_BEGIN 20 | 21 | /* MSVC DLL import/export. */ 22 | #ifdef _MSC_VER 23 | #ifdef _CINDEX_LIB_ 24 | #define CINDEX_LINKAGE __declspec(dllexport) 25 | #else 26 | #define CINDEX_LINKAGE __declspec(dllimport) 27 | #endif 28 | #else 29 | #define CINDEX_LINKAGE 30 | #endif 31 | 32 | #ifdef __GNUC__ 33 | #define CINDEX_DEPRECATED __attribute__((deprecated)) 34 | #else 35 | #ifdef _MSC_VER 36 | #define CINDEX_DEPRECATED __declspec(deprecated) 37 | #else 38 | #define CINDEX_DEPRECATED 39 | #endif 40 | #endif 41 | 42 | LLVM_CLANG_C_EXTERN_C_END 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /test/collision_tests/expected_bindings/_expected_reserved_keyword_collision_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | class Bindings { 8 | /// Holds the symbol lookup function. 9 | final ffi.Pointer Function(String symbolName) 10 | _lookup; 11 | 12 | /// The symbols are looked up in [dynamicLibrary]. 13 | Bindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; 14 | 15 | /// The symbols are looked up with [lookup]. 16 | Bindings.fromLookup( 17 | ffi.Pointer Function(String symbolName) 18 | lookup) 19 | : _lookup = lookup; 20 | 21 | void show1() { 22 | return _show1(); 23 | } 24 | 25 | late final _show1Ptr = 26 | _lookup>('show'); 27 | late final _show1 = _show1Ptr.asFunction(); 28 | 29 | void implements1( 30 | int if1, 31 | int abstract1, 32 | int in1, 33 | ) { 34 | return _implements1( 35 | if1, 36 | abstract1, 37 | in1, 38 | ); 39 | } 40 | 41 | late final _implements1Ptr = 42 | _lookup>( 43 | 'implements'); 44 | late final _implements1 = 45 | _implements1Ptr.asFunction(); 46 | } 47 | 48 | final class abstract1 extends ffi.Opaque {} 49 | 50 | final class abstract2 extends ffi.Opaque {} 51 | 52 | final class if1 extends ffi.Opaque {} 53 | 54 | abstract class return1 {} 55 | 56 | abstract class export1 {} 57 | 58 | const int else1 = 0; 59 | 60 | typedef var1 = ffi.Void; 61 | typedef Dartvar = void; 62 | -------------------------------------------------------------------------------- /test/header_parser_tests/typedef_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser.dart' as parser; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:logging/logging.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../test_utils.dart'; 12 | 13 | late Library actual, expected; 14 | 15 | void main() { 16 | group('typedef_test', () { 17 | setUpAll(() { 18 | logWarnings(Level.SEVERE); 19 | actual = parser.parse( 20 | testConfig(''' 21 | ${strings.name}: 'Bindings' 22 | ${strings.description}: 'Typedef Test' 23 | ${strings.output}: 'unused' 24 | 25 | ${strings.headers}: 26 | ${strings.entryPoints}: 27 | - 'test/header_parser_tests/typedef.h' 28 | ${strings.includeDirectives}: 29 | - '**typedef.h' 30 | ${strings.structs}: 31 | ${strings.exclude}: 32 | - ExcludedStruct 33 | - _ExcludedStruct 34 | ${strings.typeMap}: 35 | ${strings.typeMapTypedefs}: 36 | 'SpecifiedTypeAsIntPtr': 37 | lib: 'ffi' 38 | c-type: 'IntPtr' 39 | dart-type: 'int' 40 | ${strings.preamble}: | 41 | // ignore_for_file: unused_element, unused_field 42 | '''), 43 | ); 44 | }); 45 | 46 | test('Expected Bindings', () { 47 | matchLibraryWithExpected( 48 | actual, 'header_parser_typedef_test_output.dart', [ 49 | 'test', 50 | 'header_parser_tests', 51 | 'expected_bindings', 52 | '_expected_typedef_bindings.dart' 53 | ]); 54 | }); 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /test/collision_tests/decl_symbol_address_collision_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:test/test.dart'; 8 | import '../test_utils.dart'; 9 | 10 | late Library actual; 11 | void main() { 12 | group('decl_symbol_address_collision_test', () { 13 | setUpAll(() { 14 | logWarnings(Level.SEVERE); 15 | actual = Library( 16 | name: 'Bindings', 17 | header: 18 | '// ignore_for_file: unused_element, camel_case_types, non_constant_identifier_names\n', 19 | bindings: [ 20 | Struct(name: 'addresses'), 21 | Struct(name: '_SymbolAddresses'), 22 | EnumClass(name: 'Bindings'), 23 | Func( 24 | name: '_library', 25 | returnType: NativeType(SupportedNativeType.Void), 26 | exposeSymbolAddress: true, 27 | exposeFunctionTypedefs: true, 28 | ), 29 | Func( 30 | name: '_SymbolAddresses_1', 31 | returnType: NativeType(SupportedNativeType.Void), 32 | exposeSymbolAddress: true, 33 | ), 34 | ], 35 | ); 36 | }); 37 | test('declaration and symbol address conflict', () { 38 | matchLibraryWithExpected( 39 | actual, 'collision_test_decl_symbol_address_collision_output.dart', [ 40 | 'test', 41 | 'collision_tests', 42 | 'expected_bindings', 43 | '_expected_decl_symbol_address_collision_bindings.dart' 44 | ]); 45 | }); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /test/example_tests/objective_c_example_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'package:ffigen/src/header_parser.dart'; 9 | import 'package:logging/logging.dart'; 10 | import 'package:path/path.dart' as path; 11 | import 'package:test/test.dart'; 12 | 13 | import '../test_utils.dart'; 14 | 15 | void main() { 16 | group('objective_c_example_test', () { 17 | setUpAll(() { 18 | logWarnings(Level.SEVERE); 19 | }); 20 | 21 | test('objective_c', () { 22 | final config = testConfigFromPath( 23 | path.join('example', 'objective_c', 'config.yaml')); 24 | final output = parse(config).generate(); 25 | 26 | // Verify that the output contains all the methods and classes that the 27 | // example app uses. 28 | expect(output, contains('class AVFAudio{')); 29 | expect(output, contains('class NSString extends NSObject {')); 30 | expect(output, contains('class NSURL extends NSObject {')); 31 | expect( 32 | output, 33 | contains( 34 | 'static NSURL fileURLWithPath_(AVFAudio _lib, NSString path) {')); 35 | expect(output, contains('class AVAudioPlayer extends NSObject {')); 36 | expect( 37 | output, 38 | contains('AVAudioPlayer? initWithContentsOfURL_error_(' 39 | 'NSURL url, ffi.Pointer> outError) {')); 40 | expect(output, contains('double get duration {')); 41 | expect(output, contains('bool play() {')); 42 | }); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /test/native_objc_test/static_func_test.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #import 6 | 7 | #include "util.h" 8 | 9 | @interface StaticFuncTestObj : NSObject { 10 | int32_t* counter; 11 | } 12 | + (instancetype)newWithCounter:(int32_t*) _counter; 13 | - (instancetype)initWithCounter:(int32_t*) _counter; 14 | - (void)setCounter:(int32_t*) _counter; 15 | - (void)dealloc; 16 | @end 17 | 18 | StaticFuncTestObj* staticFuncOfObject(StaticFuncTestObj* a) { 19 | return a; 20 | } 21 | 22 | StaticFuncTestObj* _Nullable staticFuncOfNullableObject( 23 | StaticFuncTestObj* _Nullable a) { 24 | return a; 25 | } 26 | 27 | typedef int32_t (^IntBlock)(int32_t); 28 | IntBlock staticFuncOfBlock(IntBlock a) { 29 | return a; 30 | } 31 | 32 | NS_RETURNS_RETAINED StaticFuncTestObj* staticFuncReturnsRetained( 33 | int32_t* counter) { 34 | return [StaticFuncTestObj newWithCounter: counter]; 35 | } 36 | 37 | NS_RETURNS_RETAINED StaticFuncTestObj* staticFuncReturnsRetainedArg( 38 | StaticFuncTestObj* a) { 39 | return [a retain]; 40 | } 41 | 42 | 43 | @implementation StaticFuncTestObj 44 | + (instancetype)newWithCounter:(int32_t*) _counter { 45 | return [[StaticFuncTestObj alloc] initWithCounter: _counter]; 46 | } 47 | 48 | - (instancetype)initWithCounter:(int32_t*) _counter { 49 | counter = _counter; 50 | ++*counter; 51 | return [super init]; 52 | } 53 | 54 | - (void)setCounter:(int32_t*) _counter { 55 | counter = _counter; 56 | ++*counter; 57 | } 58 | 59 | - (void)dealloc { 60 | if (counter != nil) --*counter; 61 | [super dealloc]; 62 | } 63 | @end 64 | -------------------------------------------------------------------------------- /test/native_objc_test/is_instance_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | 7 | @TestOn('mac-os') 8 | 9 | import 'dart:ffi'; 10 | import 'dart:io'; 11 | 12 | import 'package:test/test.dart'; 13 | import '../test_utils.dart'; 14 | import 'is_instance_bindings.dart'; 15 | import 'util.dart'; 16 | 17 | void main() { 18 | late IsInstanceTestObjCLibrary lib; 19 | 20 | group('isInstance', () { 21 | setUpAll(() { 22 | logWarnings(); 23 | final dylib = File('test/native_objc_test/is_instance_test.dylib'); 24 | verifySetupFile(dylib); 25 | lib = IsInstanceTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 26 | generateBindingsForCoverage('is_instance'); 27 | }); 28 | 29 | test('Unrelated classes', () { 30 | final base = NSObject.castFrom(BaseClass.new1(lib)); 31 | final unrelated = NSObject.castFrom(UnrelatedClass.new1(lib)); 32 | expect(BaseClass.isInstance(base), isTrue); 33 | expect(BaseClass.isInstance(unrelated), isFalse); 34 | expect(UnrelatedClass.isInstance(base), isFalse); 35 | expect(UnrelatedClass.isInstance(unrelated), isTrue); 36 | }); 37 | 38 | test('Base class vs child class', () { 39 | final base = NSObject.castFrom(BaseClass.new1(lib)); 40 | final child = NSObject.castFrom(ChildClass.new1(lib)); 41 | expect(BaseClass.isInstance(base), isTrue); 42 | expect(BaseClass.isInstance(child), isTrue); 43 | expect(ChildClass.isInstance(base), isFalse); 44 | expect(ChildClass.isInstance(child), isTrue); 45 | }); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /test/code_generator_tests/expected_bindings/_expected_typealias_bindings.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | import 'dart:ffi' as ffi; 8 | 9 | class Bindings { 10 | /// Holds the symbol lookup function. 11 | final ffi.Pointer Function(String symbolName) 12 | _lookup; 13 | 14 | /// The symbols are looked up in [dynamicLibrary]. 15 | Bindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; 16 | 17 | /// The symbols are looked up with [lookup]. 18 | Bindings.fromLookup( 19 | ffi.Pointer Function(String symbolName) 20 | lookup) 21 | : _lookup = lookup; 22 | 23 | ffi.Pointer> WithTypealiasStruct1( 24 | Struct3Typealias t, 25 | ) { 26 | return _WithTypealiasStruct1( 27 | t, 28 | ); 29 | } 30 | 31 | late final _WithTypealiasStruct1Ptr = _lookup< 32 | ffi.NativeFunction< 33 | ffi.Pointer> Function( 34 | Struct3Typealias)>>('WithTypealiasStruct'); 35 | late final _WithTypealiasStruct1 = _WithTypealiasStruct1Ptr.asFunction< 36 | ffi.Pointer> Function( 37 | Struct3Typealias)>(); 38 | } 39 | 40 | typedef RawUnused = Struct1; 41 | 42 | final class Struct1 extends ffi.Opaque {} 43 | 44 | final class WithTypealiasStruct extends ffi.Struct { 45 | external Struct2Typealias t; 46 | } 47 | 48 | typedef Struct2Typealias = Struct2; 49 | 50 | final class Struct2 extends ffi.Struct { 51 | @ffi.Double() 52 | external double a; 53 | } 54 | 55 | typedef Struct3Typealias = Struct3; 56 | 57 | final class Struct3 extends ffi.Opaque {} 58 | -------------------------------------------------------------------------------- /test/header_parser_tests/varargs_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/config_provider.dart'; 7 | import 'package:ffigen/src/header_parser.dart' as parser; 8 | import 'package:ffigen/src/strings.dart' as strings; 9 | import 'package:test/test.dart'; 10 | import 'package:yaml/yaml.dart' as yaml; 11 | 12 | import '../test_utils.dart'; 13 | 14 | late Library actual, expected; 15 | 16 | void main() { 17 | group('varargs_test', () { 18 | setUpAll(() { 19 | logWarnings(); 20 | actual = parser.parse( 21 | Config.fromYaml(yaml.loadYaml(''' 22 | ${strings.name}: 'NativeLibrary' 23 | ${strings.description}: 'VarArgs Test' 24 | ${strings.output}: 'unused' 25 | 26 | ${strings.headers}: 27 | ${strings.entryPoints}: 28 | - 'test/header_parser_tests/varargs.h' 29 | 30 | ${strings.functions}: 31 | ${strings.varArgFunctions}: 32 | myfunc: 33 | - [int, char*, SA] 34 | myfunc2: 35 | - [char*, long**] 36 | - [SA, int*, unsigned char**] 37 | - types: [SA, int*, unsigned char**] 38 | postfix: _custompostfix 39 | myfunc3: 40 | - [Struct_WithLong_Name_test*, float*] 41 | - types: [Struct_WithLong_Name_test] 42 | postfix: _custompostfix2 43 | 44 | ${strings.preamble}: | 45 | // ignore_for_file: camel_case_types 46 | ''') as yaml.YamlMap), 47 | ); 48 | }); 49 | test('Expected Bindings', () { 50 | matchLibraryWithExpected( 51 | actual, 'header_parser_varargs_test_output.dart', [ 52 | 'test', 53 | 'header_parser_tests', 54 | 'expected_bindings', 55 | '_expected_varargs_bindings.dart' 56 | ]); 57 | }); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /example/shared_bindings/lib/generated/base_gen.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names, camel_case_types 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | import 'dart:ffi' as ffi; 8 | 9 | /// Bindings to `headers/base.h`. 10 | class NativeLibraryBase { 11 | /// Holds the symbol lookup function. 12 | final ffi.Pointer Function(String symbolName) 13 | _lookup; 14 | 15 | /// The symbols are looked up in [dynamicLibrary]. 16 | NativeLibraryBase(ffi.DynamicLibrary dynamicLibrary) 17 | : _lookup = dynamicLibrary.lookup; 18 | 19 | /// The symbols are looked up with [lookup]. 20 | NativeLibraryBase.fromLookup( 21 | ffi.Pointer Function(String symbolName) 22 | lookup) 23 | : _lookup = lookup; 24 | 25 | void base_func1( 26 | BaseTypedef1 t1, 27 | BaseTypedef2 t2, 28 | ) { 29 | return _base_func1( 30 | t1, 31 | t2, 32 | ); 33 | } 34 | 35 | late final _base_func1Ptr = _lookup< 36 | ffi.NativeFunction>( 37 | 'base_func1'); 38 | late final _base_func1 = 39 | _base_func1Ptr.asFunction(); 40 | } 41 | 42 | final class BaseStruct1 extends ffi.Struct { 43 | @ffi.Int() 44 | external int a; 45 | } 46 | 47 | final class BaseUnion1 extends ffi.Union { 48 | @ffi.Int() 49 | external int a; 50 | } 51 | 52 | final class BaseStruct2 extends ffi.Struct { 53 | @ffi.Int() 54 | external int a; 55 | } 56 | 57 | final class BaseUnion2 extends ffi.Union { 58 | @ffi.Int() 59 | external int a; 60 | } 61 | 62 | abstract class BaseEnum { 63 | static const int BASE_ENUM_1 = 0; 64 | static const int BASE_ENUM_2 = 1; 65 | } 66 | 67 | typedef BaseTypedef1 = BaseStruct1; 68 | typedef BaseTypedef2 = BaseStruct2; 69 | 70 | const int BASE_MACRO_1 = 1; 71 | -------------------------------------------------------------------------------- /lib/src/header_parser/sub_parsers/var_parser.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:ffigen/src/header_parser/data.dart'; 7 | import 'package:ffigen/src/header_parser/includer.dart'; 8 | import 'package:logging/logging.dart'; 9 | 10 | import '../clang_bindings/clang_bindings.dart' as clang_types; 11 | import '../utils.dart'; 12 | 13 | final _logger = Logger('ffigen.header_parser.var_parser'); 14 | 15 | /// Parses a global variable 16 | Global? parseVarDeclaration(clang_types.CXCursor cursor) { 17 | final name = cursor.spelling(); 18 | final usr = cursor.usr(); 19 | if (bindingsIndex.isSeenGlobalVar(usr)) { 20 | return bindingsIndex.getSeenGlobalVar(usr); 21 | } 22 | if (!shouldIncludeGlobalVar(usr, name)) { 23 | return null; 24 | } 25 | 26 | _logger.fine('++++ Adding Global: ${cursor.completeStringRepr()}'); 27 | 28 | final type = cursor.type().toCodeGenType(); 29 | if (type.baseType is UnimplementedType) { 30 | _logger.fine('---- Removed Global, reason: unsupported type: ' 31 | '${cursor.completeStringRepr()}'); 32 | _logger.warning("Skipped global variable '$name', type not supported."); 33 | return null; 34 | } 35 | 36 | if (config.ffiNativeConfig.enabled) { 37 | _logger 38 | .warning("Skipped global variable '$name', not supported in Natives."); 39 | return null; 40 | } 41 | 42 | final global = Global( 43 | originalName: name, 44 | name: config.globals.renameUsingConfig(name), 45 | usr: usr, 46 | type: type, 47 | dartDoc: getCursorDocComment(cursor), 48 | exposeSymbolAddress: config.functionDecl.shouldIncludeSymbolAddress(name), 49 | ); 50 | bindingsIndex.addGlobalVarToSeen(usr, global); 51 | return global; 52 | } 53 | -------------------------------------------------------------------------------- /lib/src/header_parser/sub_parsers/function_type_param_parser.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:ffi'; 6 | 7 | import '../clang_bindings/clang_bindings.dart'; 8 | import '../data.dart'; 9 | import '../utils.dart'; 10 | 11 | /// This type holds the list of `ParmDecl` nodes of a function type declaration. 12 | class FunctionTypeParams { 13 | final List paramNames; 14 | final Map params; 15 | FunctionTypeParams() 16 | : paramNames = [], 17 | params = {}; 18 | } 19 | 20 | FunctionTypeParams? _params; 21 | 22 | int _functionPointerFieldVisitor( 23 | CXCursor cursor, CXCursor parent, Pointer clientData) { 24 | if (cursor.kind == CXCursorKind.CXCursor_ParmDecl) { 25 | final spelling = cursor.spelling(); 26 | if (spelling.isNotEmpty) { 27 | _params!.paramNames.add(spelling); 28 | _params!.params[spelling] = cursor; 29 | return CXChildVisitResult.CXChildVisit_Continue; 30 | } else { 31 | // A parameter's spelling is empty, do not continue further traversal. 32 | _params!.paramNames.clear(); 33 | _params!.params.clear(); 34 | return CXChildVisitResult.CXChildVisit_Break; 35 | } 36 | } 37 | // The cursor itself may be a pointer etc.. 38 | return CXChildVisitResult.CXChildVisit_Recurse; 39 | } 40 | 41 | /// Returns `ParmDecl` nodes of function pointer declaration 42 | /// directly or indirectly pointed to by [cursor]. 43 | FunctionTypeParams parseFunctionPointerParamNames(CXCursor cursor) { 44 | _params = FunctionTypeParams(); 45 | clang.clang_visitChildren( 46 | cursor, 47 | Pointer.fromFunction( 48 | _functionPointerFieldVisitor, exceptional_visitor_return), 49 | nullptr, 50 | ); 51 | final result = _params; 52 | _params = null; 53 | return result!; 54 | } 55 | -------------------------------------------------------------------------------- /test/header_parser_tests/typedef.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #include 6 | 7 | typedef void (*NamedFunctionProto)(); 8 | 9 | struct Struct1 10 | { 11 | NamedFunctionProto named; 12 | void (*unnamed)(); 13 | }; 14 | 15 | extern NamedFunctionProto func1(NamedFunctionProto named, void (*unnamed)(int)); 16 | 17 | typedef struct 18 | { 19 | 20 | } AnonymousStructInTypedef; 21 | // These typerefs do not affect the name of AnonymousStructInTypedef. 22 | typedef AnonymousStructInTypedef Typeref1; 23 | typedef AnonymousStructInTypedef Typeref2; 24 | 25 | // Name from global namespace is used. 26 | typedef struct _NamedStructInTypedef 27 | { 28 | 29 | } NamedStructInTypedef; 30 | 31 | // Both these names must be exlucded or this struct will be generated. 32 | typedef struct _ExcludedStruct 33 | { 34 | 35 | } ExcludedStruct; 36 | typedef ExcludedStruct NTyperef1; 37 | 38 | // Because `struct _ExcludedStruct` is excluded, the type name used 39 | // in this function (the first function) will be used. 40 | // Therefore, _ExcludedStruct will be generated as NTyperef1. 41 | void func2(NTyperef1 *); 42 | 43 | typedef enum 44 | { 45 | a = 0 46 | } AnonymousEnumInTypedef; 47 | 48 | // Name from global namespace is used. 49 | typedef enum _NamedEnumInTypedef 50 | { 51 | b = 0 52 | } NamedEnumInTypedef; 53 | 54 | // Should be treated as IntPtr when used. 55 | typedef char SpecifiedTypeAsIntPtr; 56 | typedef SpecifiedTypeAsIntPtr NestingASpecifiedType; 57 | 58 | void func3(SpecifiedTypeAsIntPtr, NestingASpecifiedType b); 59 | 60 | // Struct3 is used. `pStruct2` and `pStruct3` are ignored. 61 | typedef struct 62 | { 63 | } Struct2, Struct3, *pStruct2, *pStruct3; 64 | 65 | typedef bool BoolAlias; 66 | 67 | BoolAlias func4(BoolAlias *a); 68 | 69 | struct WithBoolAlias{ 70 | BoolAlias b; 71 | }; 72 | -------------------------------------------------------------------------------- /test/native_test/native_test.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | #define aloc(T) ((T *)malloc(sizeof(T))) 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | bool Function1Bool(bool x) { return !x; } 11 | 12 | uint8_t Function1Uint8(uint8_t x) { return x + 42; } 13 | 14 | uint16_t Function1Uint16(uint16_t x) { return x + 42; } 15 | 16 | uint32_t Function1Uint32(uint32_t x) { return x + 42; } 17 | 18 | uint64_t Function1Uint64(uint64_t x) { return x + 42; } 19 | 20 | int8_t Function1Int8(int8_t x) { return x + 42; } 21 | 22 | int16_t Function1Int16(int16_t x) { return x + 42; } 23 | 24 | int32_t Function1Int32(int32_t x) { return x + 42; } 25 | 26 | int64_t Function1Int64(int64_t x) { return x + 42; } 27 | 28 | intptr_t Function1IntPtr(intptr_t x) { return x + 42; } 29 | 30 | uintptr_t Function1UintPtr(uintptr_t x) { return x + 42; } 31 | 32 | float Function1Float(float x) { return x + 42.0f; } 33 | 34 | double Function1Double(double x) { return x + 42.0; } 35 | 36 | struct Struct1 37 | { 38 | int8_t a; 39 | int32_t data[3][1][2]; 40 | }; 41 | 42 | struct Struct1 *getStruct1() 43 | { 44 | struct Struct1 *s = aloc(struct Struct1); 45 | s->a = 0; 46 | s->data[0][0][0] = 1; 47 | s->data[0][0][1] = 2; 48 | s->data[1][0][0] = 3; 49 | s->data[1][0][1] = 4; 50 | s->data[2][0][0] = 5; 51 | s->data[2][0][1] = 6; 52 | return s; 53 | } 54 | 55 | struct Struct3 56 | { 57 | int a; 58 | int b; 59 | int c; 60 | }; 61 | 62 | struct Struct3 Function1StructReturnByValue(int a, int b, int c) 63 | { 64 | struct Struct3 s; 65 | s.a = a; 66 | s.b = b; 67 | s.c = c; 68 | return s; 69 | } 70 | 71 | int Function1StructPassByValue(struct Struct3 sum_a_b_c) 72 | { 73 | return sum_a_b_c.a + sum_a_b_c.b + sum_a_b_c.c; 74 | } 75 | -------------------------------------------------------------------------------- /test/collision_tests/reserved_keyword_collision_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/src/code_generator.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:test/test.dart'; 8 | 9 | import '../test_utils.dart'; 10 | 11 | void main() { 12 | group('reserved_keyword_collision_test', () { 13 | setUpAll(() { 14 | logWarnings(Level.SEVERE); 15 | }); 16 | test('reserved keyword collision', () { 17 | final library = Library(name: 'Bindings', bindings: [ 18 | Struct(name: 'abstract'), 19 | Struct(name: 'abstract'), 20 | Struct(name: 'if'), 21 | EnumClass(name: 'return'), 22 | EnumClass(name: 'export'), 23 | Func(name: 'show', returnType: NativeType(SupportedNativeType.Void)), 24 | Func( 25 | name: 'implements', 26 | parameters: [ 27 | Parameter( 28 | type: intType, 29 | name: 'if', 30 | ), 31 | Parameter( 32 | type: intType, 33 | name: 'abstract', 34 | ), 35 | Parameter( 36 | type: intType, 37 | name: 'in', 38 | ), 39 | ], 40 | returnType: NativeType(SupportedNativeType.Void)), 41 | Constant( 42 | name: 'else', 43 | rawType: 'int', 44 | rawValue: '0', 45 | ), 46 | Typealias(name: 'var', type: NativeType(SupportedNativeType.Void)), 47 | ]); 48 | matchLibraryWithExpected( 49 | library, 'reserved_keyword_collision_test_output.dart', [ 50 | 'test', 51 | 'collision_tests', 52 | 'expected_bindings', 53 | '_expected_reserved_keyword_collision_bindings.dart', 54 | ]); 55 | }); 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /example/libclang-example/custom_import.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:ffi'; 6 | 7 | /// Represents a native unsigned pointer-sized integer in C. 8 | /// 9 | /// [UintPtr] is not constructible in the Dart code and serves purely as marker in 10 | /// type signatures. 11 | @AbiSpecificIntegerMapping({ 12 | Abi.androidArm: Uint32(), 13 | Abi.androidArm64: Uint64(), 14 | Abi.androidIA32: Uint32(), 15 | Abi.androidX64: Uint64(), 16 | Abi.fuchsiaArm64: Uint64(), 17 | Abi.fuchsiaX64: Uint64(), 18 | Abi.iosArm: Uint32(), 19 | Abi.iosArm64: Uint64(), 20 | Abi.iosX64: Uint64(), 21 | Abi.linuxArm: Uint32(), 22 | Abi.linuxArm64: Uint64(), 23 | Abi.linuxIA32: Uint32(), 24 | Abi.linuxX64: Uint64(), 25 | Abi.macosArm64: Uint64(), 26 | Abi.macosX64: Uint64(), 27 | Abi.windowsArm64: Uint64(), 28 | Abi.windowsIA32: Uint32(), 29 | Abi.windowsX64: Uint64(), 30 | }) 31 | final class UintPtr extends AbiSpecificInteger { 32 | const UintPtr(); 33 | } 34 | 35 | /// `unsigned long` in C. 36 | /// 37 | /// [UnsignedLong] is not constructible in the Dart code and serves purely as marker in 38 | /// type signatures. 39 | @AbiSpecificIntegerMapping({ 40 | Abi.androidArm: Uint32(), 41 | Abi.androidArm64: Uint64(), 42 | Abi.androidIA32: Uint32(), 43 | Abi.androidX64: Uint64(), 44 | Abi.fuchsiaArm64: Uint64(), 45 | Abi.fuchsiaX64: Uint64(), 46 | Abi.iosArm: Uint32(), 47 | Abi.iosArm64: Uint64(), 48 | Abi.iosX64: Uint64(), 49 | Abi.linuxArm: Uint32(), 50 | Abi.linuxArm64: Uint64(), 51 | Abi.linuxIA32: Uint32(), 52 | Abi.linuxX64: Uint64(), 53 | Abi.macosArm64: Uint64(), 54 | Abi.macosX64: Uint64(), 55 | Abi.windowsArm64: Uint32(), 56 | Abi.windowsIA32: Uint32(), 57 | Abi.windowsX64: Uint32(), 58 | }) 59 | final class UnsignedLong extends AbiSpecificInteger { 60 | const UnsignedLong(); 61 | } 62 | 63 | final class CXCursorSetImpl extends Opaque {} 64 | -------------------------------------------------------------------------------- /test/collision_tests/expected_bindings/_expected_decl_symbol_address_collision_bindings.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: unused_element, camel_case_types, non_constant_identifier_names 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | import 'dart:ffi' as ffi; 8 | 9 | class Bindings1 { 10 | /// Holds the symbol lookup function. 11 | final ffi.Pointer Function(String symbolName) 12 | _lookup; 13 | 14 | /// The symbols are looked up in [dynamicLibrary]. 15 | Bindings1(ffi.DynamicLibrary dynamicLibrary) 16 | : _lookup = dynamicLibrary.lookup; 17 | 18 | /// The symbols are looked up with [lookup]. 19 | Bindings1.fromLookup( 20 | ffi.Pointer Function(String symbolName) 21 | lookup) 22 | : _lookup = lookup; 23 | 24 | void _library() { 25 | return __library(); 26 | } 27 | 28 | late final __libraryPtr = 29 | _lookup>('_library'); 30 | late final __library = __libraryPtr.asFunction(); 31 | 32 | void _SymbolAddresses_1() { 33 | return __SymbolAddresses_1(); 34 | } 35 | 36 | late final __SymbolAddresses_1Ptr = 37 | _lookup>('_SymbolAddresses_1'); 38 | late final __SymbolAddresses_1 = 39 | __SymbolAddresses_1Ptr.asFunction(); 40 | 41 | late final addresses = _SymbolAddresses1(this); 42 | } 43 | 44 | class _SymbolAddresses1 { 45 | final Bindings1 _library1; 46 | _SymbolAddresses1(this._library1); 47 | ffi.Pointer> get _library => 48 | _library1.__libraryPtr; 49 | ffi.Pointer> get _SymbolAddresses_1 => 50 | _library1.__SymbolAddresses_1Ptr; 51 | } 52 | 53 | final class addresses extends ffi.Opaque {} 54 | 55 | final class _SymbolAddresses extends ffi.Opaque {} 56 | 57 | abstract class Bindings {} 58 | 59 | typedef Native_library = ffi.Void Function(); 60 | typedef Dart_library = void Function(); 61 | -------------------------------------------------------------------------------- /test/header_parser_tests/expected_bindings/_expected_comment_markup_bindings.dart: -------------------------------------------------------------------------------- 1 | // AUTO GENERATED FILE, DO NOT EDIT. 2 | // 3 | // Generated by `package:ffigen`. 4 | // ignore_for_file: type=lint 5 | import 'dart:ffi' as ffi; 6 | 7 | /// Comment Markup Test 8 | class NativeLibrary { 9 | /// Holds the symbol lookup function. 10 | final ffi.Pointer Function(String symbolName) 11 | _lookup; 12 | 13 | /// The symbols are looked up in [dynamicLibrary]. 14 | NativeLibrary(ffi.DynamicLibrary dynamicLibrary) 15 | : _lookup = dynamicLibrary.lookup; 16 | 17 | /// The symbols are looked up with [lookup]. 18 | NativeLibrary.fromLookup( 19 | ffi.Pointer Function(String symbolName) 20 | lookup) 21 | : _lookup = lookup; 22 | 23 | /// This is a single line test comment. 24 | void com1() { 25 | return _com1(); 26 | } 27 | 28 | late final _com1Ptr = 29 | _lookup>('com1'); 30 | late final _com1 = _com1Ptr.asFunction(); 31 | 32 | /// This is a multi-line 33 | /// test comment. 34 | void com2() { 35 | return _com2(); 36 | } 37 | 38 | late final _com2Ptr = 39 | _lookup>('com2'); 40 | late final _com2 = _com2Ptr.asFunction(); 41 | 42 | /// This is a multi-line 43 | /// doxygen style 44 | /// test comment. 45 | void com3() { 46 | return _com3(); 47 | } 48 | 49 | late final _com3Ptr = 50 | _lookup>('com3'); 51 | late final _com3 = _com3Ptr.asFunction(); 52 | } 53 | 54 | /// Test comment for struct. 55 | final class Com4 extends ffi.Struct { 56 | /// Muli-line test comment for struct field 57 | /// With multiple line and both // and ///. 58 | @ffi.Int() 59 | external int a; 60 | 61 | /// Single line field comment. 62 | @ffi.Float() 63 | external double b; 64 | 65 | /// Comment on array member. 66 | @ffi.Array.multi([3]) 67 | external ffi.Array c; 68 | } 69 | -------------------------------------------------------------------------------- /test/config_tests/packed_struct_override_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:ffigen/ffigen.dart'; 6 | import 'package:ffigen/src/code_generator.dart'; 7 | import 'package:ffigen/src/strings.dart' as strings; 8 | import 'package:test/test.dart'; 9 | 10 | import '../test_utils.dart'; 11 | 12 | late Library actual, expected; 13 | 14 | void main() { 15 | group('packed_struct_override_test', () { 16 | test('Invalid Packed Config values', () { 17 | const baseYaml = '''${strings.name}: 'NativeLibrary' 18 | ${strings.description}: 'Packed Struct Override Test' 19 | ${strings.output}: 'unused' 20 | ${strings.headers}: 21 | ${strings.entryPoints}: 22 | - 'test/header_parser_tests/packed_structs.h' 23 | ${strings.structs}: 24 | ${strings.structPack}: 25 | '''; 26 | expect(() => testConfig("$baseYaml'.*': null"), 27 | throwsA(TypeMatcher())); 28 | expect(() => testConfig("$baseYaml'.*': 3"), 29 | throwsA(TypeMatcher())); 30 | expect(() => testConfig("$baseYaml'.*': 32"), 31 | throwsA(TypeMatcher())); 32 | }); 33 | test('Override values', () { 34 | final config = testConfig(''' 35 | ${strings.name}: 'NativeLibrary' 36 | ${strings.description}: 'Packed Struct Override Test' 37 | ${strings.output}: 'unused' 38 | ${strings.headers}: 39 | ${strings.entryPoints}: 40 | - 'test/header_parser_tests/packed_structs.h' 41 | ${strings.structs}: 42 | ${strings.structPack}: 43 | 'Normal.*': 1 44 | 'StructWithAttr': 2 45 | 'PackedAttr': none 46 | '''); 47 | 48 | final library = parse(config); 49 | 50 | expect((library.getBinding('NormalStruct1') as Struct).pack, 1); 51 | expect((library.getBinding('StructWithAttr') as Struct).pack, 2); 52 | expect((library.getBinding('PackedAttr') as Struct).pack, null); 53 | }); 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/header_parser/data.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:ffi'; 6 | 7 | import 'package:ffigen/src/code_generator.dart' 8 | show Constant, ObjCBuiltInFunctions; 9 | import 'package:ffigen/src/config_provider.dart' show Config; 10 | import 'clang_bindings/clang_bindings.dart' show Clang; 11 | 12 | import 'utils.dart'; 13 | 14 | /// Holds all Global shared variables. 15 | 16 | /// Holds configurations. 17 | Config get config => _config; 18 | late Config _config; 19 | 20 | /// Holds clang functions. 21 | Clang get clang => _clang; 22 | late Clang _clang; 23 | 24 | // Cursor index. 25 | CursorIndex get cursorIndex => _cursorIndex; 26 | CursorIndex _cursorIndex = CursorIndex(); 27 | 28 | // Tracks seen status for bindings 29 | BindingsIndex get bindingsIndex => _bindingsIndex; 30 | BindingsIndex _bindingsIndex = BindingsIndex(); 31 | 32 | /// Used for naming typedefs. 33 | IncrementalNamer get incrementalNamer => _incrementalNamer; 34 | IncrementalNamer _incrementalNamer = IncrementalNamer(); 35 | 36 | /// Saved macros, Key: prefixedName, Value originalName. 37 | Map get savedMacros => _savedMacros; 38 | Map _savedMacros = {}; 39 | 40 | /// Saved unnamed EnumConstants. 41 | List get unnamedEnumConstants => _unnamedEnumConstants; 42 | List _unnamedEnumConstants = []; 43 | 44 | /// Built in functions used by the Objective C bindings. 45 | ObjCBuiltInFunctions get objCBuiltInFunctions => _objCBuiltInFunctions; 46 | late ObjCBuiltInFunctions _objCBuiltInFunctions; 47 | 48 | void initializeGlobals({required Config config}) { 49 | _config = config; 50 | _clang = Clang(DynamicLibrary.open(config.libclangDylib)); 51 | _incrementalNamer = IncrementalNamer(); 52 | _savedMacros = {}; 53 | _unnamedEnumConstants = []; 54 | _cursorIndex = CursorIndex(); 55 | _bindingsIndex = BindingsIndex(); 56 | _objCBuiltInFunctions = ObjCBuiltInFunctions(); 57 | } 58 | -------------------------------------------------------------------------------- /test/native_objc_test/cast_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | 7 | @TestOn('mac-os') 8 | 9 | import 'dart:ffi'; 10 | import 'dart:io'; 11 | 12 | import 'package:test/test.dart'; 13 | import '../test_utils.dart'; 14 | import 'cast_bindings.dart'; 15 | import 'util.dart'; 16 | 17 | void main() { 18 | Castaway? testInstance; 19 | late CastTestObjCLibrary lib; 20 | 21 | group('cast', () { 22 | setUpAll(() { 23 | logWarnings(); 24 | final dylib = File('test/native_objc_test/cast_test.dylib'); 25 | verifySetupFile(dylib); 26 | lib = CastTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 27 | testInstance = Castaway.new1(lib); 28 | generateBindingsForCoverage('cast'); 29 | }); 30 | 31 | test('castFrom', () { 32 | final fromCast = Castaway.castFrom(testInstance!.meAsNSObject()); 33 | expect(fromCast, testInstance!); 34 | }); 35 | 36 | test('castFromPointer', () { 37 | final meAsInt = testInstance!.meAsInt(); 38 | final fromCast = Castaway.castFromPointer( 39 | lib, Pointer.fromAddress(meAsInt)); 40 | expect(fromCast, testInstance!); 41 | }); 42 | 43 | test('pointers are equal', () { 44 | final meAsInt = testInstance!.meAsInt(); 45 | expect(testInstance!.pointer.address, meAsInt); 46 | }); 47 | 48 | test('equality equals', () { 49 | final meAsInt = testInstance!.meAsInt(); 50 | final fromCast = Castaway.castFromPointer( 51 | lib, Pointer.fromAddress(meAsInt)); 52 | expect(fromCast, testInstance!); 53 | }); 54 | 55 | test('equality not equals', () { 56 | final meAsInt = testInstance!.meAsInt(); 57 | final fromCast = Castaway.castFromPointer( 58 | lib, Pointer.fromAddress(meAsInt)); 59 | expect(fromCast, isNot(equals(NSObject.new1(lib)))); 60 | }); 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /test/header_parser_tests/struct_fptr_fields.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | typedef int (*ArithmeticOperation)(int a, int b); 6 | 7 | struct S 8 | { 9 | // Function pointer field, but no parameters. 10 | int (*func1)(void); 11 | // Function pointer field with parameters. 12 | int (*comparator)(int a, int b); 13 | // Function pointer field with lot of parameters 14 | int (*veryManyArguments)(double a, float b, char *c, int d, long long e); 15 | // Function pointer field with parameters, but no names 16 | int (*argsDontHaveNames)(int, int, int, float, char *); 17 | // Function pointer through typedef 18 | ArithmeticOperation operation; 19 | // Pointer to function pointer 20 | void (**sortPtr)(int *array, int len); 21 | // Function pointer with a function pointer parameter 22 | void (*sortBy)(int *array, int len, int (*evaluator)(int x)); 23 | // Function where few parameters are named. This should not 24 | // produce parameters in output. 25 | void (*improperlyDeclaredParams)(int a, int, char); 26 | // Function pointer with 2 function pointer parameters 27 | void (*sortByWithFallback)(int *array, 28 | int (*primaryEvaluator)(int x), 29 | int (*fallbackEvaluator)(int x)); 30 | 31 | // TODO(#545): Handle remaining cases of parsing param names 32 | // --- 33 | // Array of function pointers. Does not produce proper output right now. 34 | void (*manyFunctions[2])(char a, char b); 35 | // Function pointer returning function pointer. Does not produce valid output. 36 | int (*(*functionReturningFunction)(int a, int b))(int c, int d); 37 | // Function pointer returning function pointer. The return type has param 38 | // names, but the function itself doesn't. This also shouldn't produce 39 | // any parameters in output. 40 | int (*(*functionReturningFunctionImproper)(int a, int b))(int, int); 41 | }; 42 | -------------------------------------------------------------------------------- /test/native_objc_test/inherited_instancetype_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | // Regression tests for https://github.com/dart-lang/ffigen/issues/486. 9 | 10 | import 'dart:ffi'; 11 | import 'dart:io'; 12 | 13 | import 'package:test/test.dart'; 14 | import '../test_utils.dart'; 15 | import 'inherited_instancetype_bindings.dart'; 16 | import 'util.dart'; 17 | 18 | void main() { 19 | late InheritedInstancetypeTestObjCLibrary lib; 20 | 21 | group('inheritedInstancetype', () { 22 | setUpAll(() { 23 | logWarnings(); 24 | final dylib = 25 | File('test/native_objc_test/inherited_instancetype_test.dylib'); 26 | verifySetupFile(dylib); 27 | lib = InheritedInstancetypeTestObjCLibrary( 28 | DynamicLibrary.open(dylib.absolute.path)); 29 | generateBindingsForCoverage('inherited_instancetype'); 30 | }); 31 | 32 | test('Ordinary init method', () { 33 | final ChildClass child = ChildClass.alloc(lib).init(); 34 | expect(child.field, 123); 35 | final ChildClass sameChild = child.getSelf(); 36 | sameChild.field = 456; 37 | expect(child.field, 456); 38 | }); 39 | 40 | test('Custom create method', () { 41 | final ChildClass child = ChildClass.create(lib); 42 | expect(child.field, 123); 43 | final ChildClass sameChild = child.getSelf(); 44 | sameChild.field = 456; 45 | expect(child.field, 456); 46 | }); 47 | 48 | test('Polymorphism', () { 49 | final ChildClass child = ChildClass.alloc(lib).init(); 50 | final BaseClass base = child; 51 | 52 | // Calling base.getSelf() should still go through ChildClass.getSelf, so 53 | // the result will have a compile time type of BaseClass, but a runtime 54 | // type of ChildClass. 55 | final BaseClass sameChild = base.getSelf(); 56 | expect(sameChild, isA()); 57 | }); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /test/native_objc_test/native_objc_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | // Objective C support is only available on mac. 6 | @TestOn('mac-os') 7 | 8 | import 'dart:ffi'; 9 | import 'dart:io'; 10 | 11 | import 'package:test/test.dart'; 12 | import '../test_utils.dart'; 13 | import 'native_objc_test_bindings.dart'; 14 | import 'util.dart'; 15 | 16 | void main() { 17 | late NativeObjCLibrary lib; 18 | group('native_objc_test', () { 19 | setUpAll(() { 20 | logWarnings(); 21 | final dylib = File('test/native_objc_test/native_objc_test.dylib'); 22 | verifySetupFile(dylib); 23 | lib = NativeObjCLibrary(DynamicLibrary.open(dylib.absolute.path)); 24 | generateBindingsForCoverage('native_objc'); 25 | }); 26 | 27 | test('Basic types', () { 28 | final foo = Foo.new1(lib); 29 | final obj = NSObject.new1(lib); 30 | 31 | foo.intVal = 123; 32 | expect(foo.intVal, 123); 33 | 34 | foo.boolVal = true; 35 | expect(foo.boolVal, true); 36 | 37 | foo.idVal = obj; 38 | expect(foo.idVal, obj); 39 | 40 | foo.selVal = Pointer.fromAddress(456); 41 | expect(foo.selVal.address, 456); 42 | 43 | foo.classVal = obj; 44 | expect(foo.classVal, obj); 45 | }); 46 | 47 | test('Interface basics, with Foo', () { 48 | final foo1 = Foo.makeFoo_(lib, 3.14159); 49 | final foo2 = Foo.makeFoo_(lib, 2.71828); 50 | 51 | expect(foo1.intVal, 3); 52 | expect(foo2.intVal, 2); 53 | 54 | expect(foo1.multiply_withOtherFoo_(false, foo2), 8); 55 | expect(foo1.multiply_withOtherFoo_(true, foo2), 6); 56 | 57 | foo1.intVal = 100; 58 | expect(foo1.multiply_withOtherFoo_(false, foo2), 8); 59 | expect(foo1.multiply_withOtherFoo_(true, foo2), 200); 60 | 61 | foo2.setDoubleVal_(1.61803); 62 | expect(foo1.multiply_withOtherFoo_(false, foo2), 5); 63 | expect(foo1.multiply_withOtherFoo_(true, foo2), 200); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /example/shared_bindings/lib/generated/a_shared_b_gen.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names, camel_case_types 2 | 3 | // AUTO GENERATED FILE, DO NOT EDIT. 4 | // 5 | // Generated by `package:ffigen`. 6 | // ignore_for_file: type=lint 7 | import 'dart:ffi' as ffi; 8 | import 'package:shared_bindings/generated/base_gen.dart' as imp1; 9 | 10 | /// Bindings to `headers/a.h` with shared definitions from `headers/base.h`. 11 | class NativeLibraryASharedB { 12 | /// Holds the symbol lookup function. 13 | final ffi.Pointer Function(String symbolName) 14 | _lookup; 15 | 16 | /// The symbols are looked up in [dynamicLibrary]. 17 | NativeLibraryASharedB(ffi.DynamicLibrary dynamicLibrary) 18 | : _lookup = dynamicLibrary.lookup; 19 | 20 | /// The symbols are looked up with [lookup]. 21 | NativeLibraryASharedB.fromLookup( 22 | ffi.Pointer Function(String symbolName) 23 | lookup) 24 | : _lookup = lookup; 25 | 26 | void a_func1() { 27 | return _a_func1(); 28 | } 29 | 30 | late final _a_func1Ptr = 31 | _lookup>('a_func1'); 32 | late final _a_func1 = _a_func1Ptr.asFunction(); 33 | 34 | void a_func2( 35 | imp1.BaseStruct2 s, 36 | imp1.BaseUnion2 u, 37 | imp1.BaseTypedef2 t, 38 | ) { 39 | return _a_func2( 40 | s, 41 | u, 42 | t, 43 | ); 44 | } 45 | 46 | late final _a_func2Ptr = _lookup< 47 | ffi.NativeFunction< 48 | ffi.Void Function(imp1.BaseStruct2, imp1.BaseUnion2, 49 | imp1.BaseTypedef2)>>('a_func2'); 50 | late final _a_func2 = _a_func2Ptr.asFunction< 51 | void Function(imp1.BaseStruct2, imp1.BaseUnion2, imp1.BaseTypedef2)>(); 52 | } 53 | 54 | final class A_Struct1 extends ffi.Struct { 55 | @ffi.Int() 56 | external int a; 57 | } 58 | 59 | final class A_Union1 extends ffi.Union { 60 | @ffi.Int() 61 | external int a; 62 | } 63 | 64 | abstract class A_Enum { 65 | static const int A_ENUM_1 = 0; 66 | static const int A_ENUM_2 = 1; 67 | } 68 | 69 | const int BASE_MACRO_1 = 1; 70 | 71 | const int A_MACRO_1 = 1; 72 | -------------------------------------------------------------------------------- /third_party/libclang/include/clang-c/ExternC.h: -------------------------------------------------------------------------------- 1 | /*===- clang-c/ExternC.h - Wrapper for 'extern "C"' ---------------*- C -*-===*\ 2 | |* *| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| 4 | |* Exceptions. *| 5 | |* See https://llvm.org/LICENSE.txt for license information. *| 6 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| 7 | |* *| 8 | |*===----------------------------------------------------------------------===*| 9 | |* *| 10 | |* This file defines an 'extern "C"' wrapper. *| 11 | |* *| 12 | \*===----------------------------------------------------------------------===*/ 13 | 14 | #ifndef LLVM_CLANG_C_EXTERN_C_H 15 | #define LLVM_CLANG_C_EXTERN_C_H 16 | 17 | #ifdef __clang__ 18 | #define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN \ 19 | _Pragma("clang diagnostic push") \ 20 | _Pragma("clang diagnostic error \"-Wstrict-prototypes\"") 21 | #define LLVM_CLANG_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop") 22 | #else 23 | #define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN 24 | #define LLVM_CLANG_C_STRICT_PROTOTYPES_END 25 | #endif 26 | 27 | #ifdef __cplusplus 28 | #define LLVM_CLANG_C_EXTERN_C_BEGIN \ 29 | extern "C" { \ 30 | LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN 31 | #define LLVM_CLANG_C_EXTERN_C_END \ 32 | LLVM_CLANG_C_STRICT_PROTOTYPES_END \ 33 | } 34 | #else 35 | #define LLVM_CLANG_C_EXTERN_C_BEGIN LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN 36 | #define LLVM_CLANG_C_EXTERN_C_END LLVM_CLANG_C_STRICT_PROTOTYPES_END 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /lib/src/code_generator/binding.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'binding_string.dart'; 6 | import 'writer.dart'; 7 | 8 | /// Base class for all Bindings. 9 | /// 10 | /// Do not extend directly, use [LookUpBinding] or [NoLookUpBinding]. 11 | abstract class Binding { 12 | /// Holds the Unified Symbol Resolution string obtained from libclang. 13 | final String usr; 14 | 15 | /// The name as it was in C. 16 | final String originalName; 17 | 18 | /// Binding name to generate, may get changed to resolve name conflicts. 19 | String name; 20 | 21 | final String? dartDoc; 22 | final bool isInternal; 23 | 24 | Binding({ 25 | required this.usr, 26 | required this.originalName, 27 | required this.name, 28 | this.dartDoc, 29 | this.isInternal = false, 30 | }); 31 | 32 | /// Get all dependencies, including itself and save them in [dependencies]. 33 | void addDependencies(Set dependencies); 34 | 35 | /// Converts a Binding to its actual string representation. 36 | /// 37 | /// Note: This does not print the typedef dependencies. 38 | /// Must call [getTypedefDependencies] first. 39 | BindingString toBindingString(Writer w); 40 | } 41 | 42 | /// Base class for bindings which look up symbols in dynamic library. 43 | abstract class LookUpBinding extends Binding { 44 | LookUpBinding({ 45 | String? usr, 46 | String? originalName, 47 | required super.name, 48 | super.dartDoc, 49 | super.isInternal, 50 | }) : super( 51 | usr: usr ?? name, 52 | originalName: originalName ?? name, 53 | ); 54 | } 55 | 56 | /// Base class for bindings which don't look up symbols in dynamic library. 57 | abstract class NoLookUpBinding extends Binding { 58 | NoLookUpBinding({ 59 | String? usr, 60 | String? originalName, 61 | required super.name, 62 | super.dartDoc, 63 | super.isInternal, 64 | }) : super( 65 | usr: usr ?? name, 66 | originalName: originalName ?? name, 67 | ); 68 | } 69 | --------------------------------------------------------------------------------