Skip to content

Commit

Permalink
[ffigen] Migrate to ARC (#1441)
Browse files Browse the repository at this point in the history
  • Loading branch information
liamappelbe authored Aug 26, 2024
1 parent 552428b commit 3d80f02
Show file tree
Hide file tree
Showing 43 changed files with 871 additions and 251 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/objective_c.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,20 @@ jobs:
carryforward: "ffigen,jni,jnigen,native_assets_builder_macos,native_assets_builder_ubuntu,native_assets_builder_windows,native_assets_cli_macos,native_assets_cli_ubuntu,native_assets_cli_windows,native_toolchain_c_macos,native_toolchain_c_ubuntu,native_toolchain_c_windows,objective_c,swift2objc"
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true

build-example:
needs: analyze
runs-on: 'macos-latest'
defaults:
run:
working-directory: pkgs/objective_c/example/
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
with:
flutter-version: 3.19.0
channel: 'stable'
- name: Install dependencies
run: flutter pub get
- name: Build the example app
run: flutter build macos
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ coverage/
*.jar
*.class
*.exe
*.o

# Visual Studio user-specific files.
*.suo
Expand Down
6 changes: 5 additions & 1 deletion pkgs/ffigen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
`ObjCBlock<Ret Function(Args...)>`, instead of the codegenned
`ObjCBlock_...` wrapper. The wrapper is now a non-constructible set of util
methods for constructing `ObjCBlock`.

- __Breaking change__: Generated ObjC code has been migrated to ARC (Automatic
Reference Counting), and must now be compiled with ARC enabled. For example,
if you had a line like `s.requires_arc = []` in your podspec, this should
either be removed, or you should add the ffigen generated ObjC code to the
list. If you're compiling directly with clang, add the `-fobjc-arc` flag.

## 13.0.0

Expand Down
34 changes: 22 additions & 12 deletions pkgs/ffigen/lib/src/code_generator/objc_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ abstract final class $name {
objCRetain: true);
final listenerConvFn =
'($paramsFfiDartType) => $listenerConvFnInvocation';
final wrapFn = _wrapListenerBlock?.name;
final releaseFn = ObjCBuiltInFunctions.objectRelease.gen(w);

s.write('''
Expand All @@ -205,12 +207,22 @@ abstract final class $name {
///
/// Note that unlike the default behavior of NativeCallable.listener, listener
/// blocks do not keep the isolate alive.
static $blockType listener($funcDartType fn) =>
$blockType(${_wrapListenerBlock?.name ?? ''}($newClosureBlock(
(_dartFuncListenerTrampoline ??= $nativeCallableType.listener(
$closureTrampoline $exceptionalReturn)..keepIsolateAlive =
false).nativeFunction.cast(), $listenerConvFn)),
retain: false, release: true);
static $blockType listener($funcDartType fn) {
final raw = $newClosureBlock(
(_dartFuncListenerTrampoline ??= $nativeCallableType.listener(
$closureTrampoline $exceptionalReturn)..keepIsolateAlive =
false).nativeFunction.cast(), $listenerConvFn);''');
if (wrapFn != null) {
s.write('''
final wrapper = $wrapFn(raw);
$releaseFn(raw.cast());
return $blockType(wrapper, retain: false, release: true);''');
} else {
s.write('''
return $blockType(raw, retain: false, release: true);''');
}
s.write('''
}
static $nativeCallableType? _dartFuncListenerTrampoline;
''');
}
Expand Down Expand Up @@ -256,12 +268,10 @@ pointer.ref.invoke.cast<$natTrampFnType>().asFunction<$trampFuncFfiDartType>()(
s.write('''
typedef ${getNativeType(varName: blockTypedef)};
$blockTypedef $fnName($blockTypedef block) {
$blockTypedef wrapper = [^void(${argsReceived.join(', ')}) {
$blockTypedef $fnName($blockTypedef block) NS_RETURNS_RETAINED {
return ^void(${argsReceived.join(', ')}) {
block(${retains.join(', ')});
} copy];
[block release];
return wrapper;
};
}
''');
return BindingString(
Expand Down Expand Up @@ -337,7 +347,7 @@ $blockTypedef $fnName($blockTypedef block) {
ObjCInterface.generateConstructor(name, value, objCRetain);

@override
String? generateRetain(String value) => '[$value copy]';
String? generateRetain(String value) => 'objc_retainBlock($value)';

@override
String toString() => '($returnType (^)(${argTypes.join(', ')}))';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ObjCBuiltInFunctions {
static const getProtocolMethodSignature =
ObjCImport('getProtocolMethodSignature');
static const getProtocol = ObjCImport('getProtocol');
static const objectRelease = ObjCImport('objectRelease');
static const objectBase = ObjCImport('ObjCObjectBase');
static const blockType = ObjCImport('ObjCBlock');
static const protocolMethod = ObjCImport('ObjCProtocolMethod');
Expand Down
2 changes: 1 addition & 1 deletion pkgs/ffigen/lib/src/code_generator/objc_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ class ObjCInterface extends BindingType with ObjCMethods {
}

@override
String? generateRetain(String value) => '[$value retain]';
String? generateRetain(String value) => 'objc_retain($value)';

String _getConvertedType(Type type, Writer w, String enclosingClass) {
if (type is ObjCInstanceType) return enclosingClass;
Expand Down
2 changes: 1 addition & 1 deletion pkgs/ffigen/lib/src/code_generator/pointer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,5 @@ class ObjCObjectPointer extends PointerType {
'${getDartType(w)}($value, retain: $objCRetain, release: true)';

@override
String? generateRetain(String value) => '[$value retain]';
String? generateRetain(String value) => 'objc_retain($value)';
}
10 changes: 9 additions & 1 deletion pkgs/ffigen/lib/src/code_generator/writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -418,12 +418,20 @@ class Writer {
final s = StringBuffer();
s.write('''
#include <stdint.h>
''');

for (final entryPoint in nativeEntryPoints) {
s.write(_objcImport(entryPoint, outDir));
}
s.write('''
#if !__has_feature(objc_arc)
#error "This file must be compiled with ARC enabled"
#endif
id objc_retain(id);
id objc_retainBlock(id);
''');

var empty = true;
for (final binding in _allBindings) {
Expand Down
17 changes: 17 additions & 0 deletions pkgs/ffigen/test/native_objc_test/arc_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: ArcTestObjCLibrary
description: 'Tests ARC'
language: objc
output: 'arc_bindings.dart'
exclude-all-by-default: true
functions:
include:
- objc_autoreleasePoolPop
- objc_autoreleasePoolPush
objc-interfaces:
include:
- ArcTestObject
headers:
entry-points:
- 'arc_test.m'
preamble: |
// ignore_for_file: camel_case_types, non_constant_identifier_names, unnecessary_non_null_assertion, unused_element, unused_field
Loading

0 comments on commit 3d80f02

Please sign in to comment.