Skip to content
This repository has been archived by the owner on Jan 28, 2024. It is now read-only.

Commit

Permalink
Better block names (#606)
Browse files Browse the repository at this point in the history
* Better Block names

* Test

* Move swift_api.h to third_party

* merge cruft
  • Loading branch information
liamappelbe authored Sep 7, 2023
1 parent 97ea620 commit 6da03b3
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 20 deletions.
8 changes: 4 additions & 4 deletions example/swift/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions example/swift/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ignore_for_file: library_private_types_in_public_api
File renamed without changes.
23 changes: 23 additions & 0 deletions lib/src/code_generator/objc_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ class ObjCBlock extends BindingType {
final ObjCBuiltInFunctions builtInFunctions;

ObjCBlock({
required String usr,
required Type returnType,
required List<Type> 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,
Expand All @@ -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<Type> 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();
Expand Down
1 change: 0 additions & 1 deletion lib/src/header_parser/sub_parsers/objc_block_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ ObjCBlock parseObjCBlock(clang_types.CXType cxtype) {

return ObjCBlock(
usr: usr.toString(),
name: 'ObjCBlock',
returnType: returnType,
argTypes: argTypes,
builtInFunctions: objCBuiltInFunctions,
Expand Down
2 changes: 1 addition & 1 deletion test/example_tests/swift_example_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
31 changes: 19 additions & 12 deletions test/native_objc_test/block_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<Char>, Pointer<Void>) executeInternalCommand;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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();
});
Expand All @@ -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();
});
Expand All @@ -102,15 +109,15 @@ 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));
expect(BlockTester.callFloatBlock_(lib, block), closeTo(5.79, 1e-6));
});

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));
Expand All @@ -127,7 +134,7 @@ void main() {

final tempPtr = calloc<Vec4>();
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;
Expand Down Expand Up @@ -156,8 +163,8 @@ void main() {
});

Pointer<Void> 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();
}
Expand All @@ -169,7 +176,7 @@ void main() {
});

Pointer<Void> 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();
}
Expand All @@ -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.
Expand Down

0 comments on commit 6da03b3

Please sign in to comment.