From 6da03b3bb63a658d1da731c143f94ba0a14a8e36 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 6 Sep 2023 18:23:56 -0700 Subject: [PATCH] Better block names (#606) * Better Block names * Test * Move swift_api.h to third_party * merge cruft --- example/swift/README.md | 8 ++--- example/swift/config.yaml | 4 +-- example/swift/{ => third_party}/swift_api.h | 0 lib/src/code_generator/objc_block.dart | 23 ++++++++++++++ .../sub_parsers/objc_block_parser.dart | 1 - test/example_tests/swift_example_test.dart | 2 +- test/native_objc_test/block_test.dart | 31 ++++++++++++------- 7 files changed, 49 insertions(+), 20 deletions(-) rename example/swift/{ => third_party}/swift_api.h (100%) diff --git a/example/swift/README.md b/example/swift/README.md index d53778e1..caa482ef 100644 --- a/example/swift/README.md +++ b/example/swift/README.md @@ -8,9 +8,9 @@ using `-emit-library`, and generate an Objective-C wrapper header using `-emit-objc-header-path filename.h`: ```shell -swiftc -c swift_api.swift \ - -module-name swift_module \ - -emit-objc-header-path swift_api.h \ +swiftc -c swift_api.swift \ + -module-name swift_module \ + -emit-objc-header-path third_party/swift_api.h \ -emit-library -o libswiftapi.dylib ``` @@ -43,7 +43,7 @@ need to set the language to objc, and set the entry-point to the header: language: objc headers: entry-points: - - 'swift_api.h' + - 'third_party/swift_api.h' ``` Swift classes become Objective-C interfaces, so include them like this: diff --git a/example/swift/config.yaml b/example/swift/config.yaml index 6082e978..7f820baa 100644 --- a/example/swift/config.yaml +++ b/example/swift/config.yaml @@ -12,10 +12,10 @@ objc-interfaces: 'SwiftClass': 'swift_module' headers: entry-points: - - 'swift_api.h' + - 'third_party/swift_api.h' preamble: | // ignore_for_file: camel_case_types, non_constant_identifier_names // ignore_for_file: unused_element, unused_field, return_of_invalid_type // ignore_for_file: void_checks, annotate_overrides // ignore_for_file: no_leading_underscores_for_local_identifiers - // ignore_for_file: library_private_types_in_public_api \ No newline at end of file + // ignore_for_file: library_private_types_in_public_api diff --git a/example/swift/swift_api.h b/example/swift/third_party/swift_api.h similarity index 100% rename from example/swift/swift_api.h rename to example/swift/third_party/swift_api.h diff --git a/lib/src/code_generator/objc_block.dart b/lib/src/code_generator/objc_block.dart index ba028d66..7bbb4c0e 100644 --- a/lib/src/code_generator/objc_block.dart +++ b/lib/src/code_generator/objc_block.dart @@ -13,6 +13,19 @@ class ObjCBlock extends BindingType { final ObjCBuiltInFunctions builtInFunctions; ObjCBlock({ + required String usr, + required Type returnType, + required List argTypes, + required ObjCBuiltInFunctions builtInFunctions, + }) : this._( + usr: usr, + name: _getBlockName(returnType, argTypes), + returnType: returnType, + argTypes: argTypes, + builtInFunctions: builtInFunctions, + ); + + ObjCBlock._({ required String usr, required String name, required this.returnType, @@ -24,6 +37,16 @@ class ObjCBlock extends BindingType { name: name, ); + // Generates a human readable name for the block based on the args and return + // type. These names will be pretty verbose and unweildy, but they're at least + // sensible and stable. Users can always add their own typedef with a simpler + // name if necessary. + static String _getBlockName(Type returnType, List argTypes) => + 'ObjCBlock_${[returnType, ...argTypes].map(_typeName).join('_')}'; + static String _typeName(Type type) => + type.toString().replaceAll(_illegalNameChar, ''); + static final _illegalNameChar = RegExp(r'[^0-9a-zA-Z]'); + @override BindingString toBindingString(Writer w) { final s = StringBuffer(); diff --git a/lib/src/header_parser/sub_parsers/objc_block_parser.dart b/lib/src/header_parser/sub_parsers/objc_block_parser.dart index f7ac6628..313de4e1 100644 --- a/lib/src/header_parser/sub_parsers/objc_block_parser.dart +++ b/lib/src/header_parser/sub_parsers/objc_block_parser.dart @@ -32,7 +32,6 @@ ObjCBlock parseObjCBlock(clang_types.CXType cxtype) { return ObjCBlock( usr: usr.toString(), - name: 'ObjCBlock', returnType: returnType, argTypes: argTypes, builtInFunctions: objCBuiltInFunctions, diff --git a/test/example_tests/swift_example_test.dart b/test/example_tests/swift_example_test.dart index 02ed00ad..a4ac61e5 100644 --- a/test/example_tests/swift_example_test.dart +++ b/test/example_tests/swift_example_test.dart @@ -31,7 +31,7 @@ void main() { '-module-name', 'swift_module', '-emit-objc-header-path', - 'swift_api.h', + 'third_party/swift_api.h', '-emit-library', '-o', 'libswiftapi.dylib', diff --git a/test/native_objc_test/block_test.dart b/test/native_objc_test/block_test.dart index 908e8fc4..0253eaf1 100644 --- a/test/native_objc_test/block_test.dart +++ b/test/native_objc_test/block_test.dart @@ -15,6 +15,13 @@ import '../test_utils.dart'; import 'block_bindings.dart'; import 'util.dart'; +// The generated block names are stable but verbose, so typedef them. +typedef IntBlock = ObjCBlock_Int32_Int32; +typedef FloatBlock = ObjCBlock_ffiFloat_ffiFloat; +typedef DoubleBlock = ObjCBlock_ffiDouble_ffiDouble; +typedef Vec4Block = ObjCBlock_Vec4_Vec4; +typedef VoidBlock = ObjCBlock_ffiVoid; + void main() { late BlockTestObjCLibrary lib; late void Function(Pointer, Pointer) executeInternalCommand; @@ -52,8 +59,8 @@ void main() { }); test('Block from function pointer', () { - final block = ObjCBlock1.fromFunctionPointer( - lib, Pointer.fromFunction(_add100, 999)); + final block = + IntBlock.fromFunctionPointer(lib, Pointer.fromFunction(_add100, 999)); final blockTester = BlockTester.makeFromBlock_(lib, block); blockTester.pokeBlock(); expect(blockTester.call_(123), 223); @@ -65,7 +72,7 @@ void main() { } test('Block from function', () { - final block = ObjCBlock1.fromFunction(lib, makeAdder(4000)); + final block = IntBlock.fromFunction(lib, makeAdder(4000)); final blockTester = BlockTester.makeFromBlock_(lib, block); blockTester.pokeBlock(); expect(blockTester.call_(123), 4123); @@ -75,7 +82,7 @@ void main() { test('Listener block same thread', () async { final hasRun = Completer(); int value = 0; - final block = ObjCBlock.listener(lib, () { + final block = VoidBlock.listener(lib, () { value = 123; hasRun.complete(); }); @@ -89,7 +96,7 @@ void main() { test('Listener block new thread', () async { final hasRun = Completer(); int value = 0; - final block = ObjCBlock.listener(lib, () { + final block = VoidBlock.listener(lib, () { value = 123; hasRun.complete(); }); @@ -102,7 +109,7 @@ void main() { }); test('Float block', () { - final block = ObjCBlock2.fromFunction(lib, (double x) { + final block = FloatBlock.fromFunction(lib, (double x) { return x + 4.56; }); expect(block(1.23), closeTo(5.79, 1e-6)); @@ -110,7 +117,7 @@ void main() { }); test('Double block', () { - final block = ObjCBlock3.fromFunction(lib, (double x) { + final block = DoubleBlock.fromFunction(lib, (double x) { return x + 4.56; }); expect(block(1.23), closeTo(5.79, 1e-6)); @@ -127,7 +134,7 @@ void main() { final tempPtr = calloc(); final temp = tempPtr.ref; - final block = ObjCBlock4.fromFunction(lib, (Vec4 v) { + final block = Vec4Block.fromFunction(lib, (Vec4 v) { // Twiddle the Vec4 components. temp.x = v.y; temp.y = v.z; @@ -156,8 +163,8 @@ void main() { }); Pointer funcPointerBlockRefCountTest() { - final block = ObjCBlock1.fromFunctionPointer( - lib, Pointer.fromFunction(_add100, 999)); + final block = + IntBlock.fromFunctionPointer(lib, Pointer.fromFunction(_add100, 999)); expect(BlockTester.getBlockRetainCount_(lib, block.pointer.cast()), 1); return block.pointer.cast(); } @@ -169,7 +176,7 @@ void main() { }); Pointer funcBlockRefCountTest() { - final block = ObjCBlock1.fromFunction(lib, makeAdder(4000)); + final block = IntBlock.fromFunction(lib, makeAdder(4000)); expect(BlockTester.getBlockRetainCount_(lib, block.pointer.cast()), 1); return block.pointer.cast(); } @@ -181,7 +188,7 @@ void main() { }); test('Block fields have sensible values', () { - final block = ObjCBlock1.fromFunction(lib, makeAdder(4000)); + final block = IntBlock.fromFunction(lib, makeAdder(4000)); final blockPtr = block.pointer; expect(blockPtr.ref.isa, isNot(0)); expect(blockPtr.ref.flags, isNot(0)); // Set by Block_copy.