Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ffigen] Migrate to ARC #1441

Merged
merged 15 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
3 changes: 3 additions & 0 deletions pkgs/ffigen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
`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, and must
now be compiled with ARC enabled. For example, if you had a line like
`s.requires_arc = []` in your podspec, this should be removed.


## 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
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
Loading