Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .github/workflows/ffigen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
- name: Check formatting
run: dart format --output=none --set-exit-if-changed .
if: always() && steps.install.outcome == 'success'
- run: git diff
- name: Build test dylib and bindings
run: dart --enable-asserts test/setup.dart
- name: Analyze code
Expand Down
11 changes: 10 additions & 1 deletion pkgs/ffigen/example/objective_c/avf_audio_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,16 @@ extension type CASpatialAudioExperience._(objc.ObjCObject object$)
}) : object$ = objc.ObjCObject(other, retain: retain, release: release) {}
}

late final _class_AVAudioPlayer = objc.getClass("AVAudioPlayer");
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_AVAudioPlayer',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_AVAudioPlayer_raw;
final _class_AVAudioPlayer = objc.getClass(
"AVAudioPlayer",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_AVAudioPlayer_raw,
).cast(),
);
final _objc_msgSend_151sglz = objc.msgSendPointer
.cast<
ffi.NativeFunction<
Expand Down
11 changes: 10 additions & 1 deletion pkgs/ffigen/example/swift/swift_api_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,16 @@ extension SwiftClass$Methods on SwiftClass {
}
}

late final _class_SwiftClass = objc.getClass("swift_module.SwiftClass");
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_swift_module.SwiftClass',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_SwiftClass_raw;
final _class_SwiftClass = objc.getClass(
"swift_module.SwiftClass",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_SwiftClass_raw,
).cast(),
);
final _objc_msgSend_151sglz = objc.msgSendPointer
.cast<
ffi.NativeFunction<
Expand Down
79 changes: 78 additions & 1 deletion pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ class ObjCImport {
String gen(Context context) => '${context.libs.prefix(objcPkgImport)}.$name';
}

/// Globals only used internally by ObjC bindings, such as classes and SELs.
/// Globals only used internally by ObjC bindings, such as selectors.
class ObjCInternalGlobal extends NoLookUpBinding {
final String Function() makeValue;

Expand All @@ -294,6 +294,83 @@ class ObjCInternalGlobal extends NoLookUpBinding {
}
}

/// A global variable for an ObjC class, loaded via @Native.
class ObjCClassGlobal extends NoLookUpBinding {
final String lookupName;
final Symbol rawSymbol;
ObjCClassGlobal(String name, this.lookupName)
: rawSymbol = Symbol('${name}_raw', SymbolKind.field),
super(
originalName: name,
symbol: Symbol(name, SymbolKind.field),
isInternal: true,
);

@override
BindingString toBindingString(Writer w) {
final context = w.context;
final ffi = context.libs.prefix(ffiImport);
final type = PointerType(objCObjectType).getCType(context);
final symbol = Namer.stringLiteral('OBJC_CLASS_\$_$lookupName');
final getClass = ObjCBuiltInFunctions.getClass.gen(context);
final address = '$ffi.Native.addressOf<$type>(${rawSymbol.name})';
final s =
'''
@$ffi.Native<$type>(symbol: '$symbol')
external $type ${rawSymbol.name};
final $name = $getClass("$lookupName", () => $address.cast());
''';
return BindingString(type: BindingStringType.global, string: s);
}

@override
void visitChildren(Visitor visitor) {
super.visitChildren(visitor);
visitor.visit(ffiImport);
visitor.visit(objcPkgImport);
visitor.visit(objCObjectType);
visitor.visit(rawSymbol);
}
}

/// A global variable for an ObjC protocol, loaded via @Native.
class ObjCProtocolGlobal extends NoLookUpBinding {
final String loaderName;
final String lookupName;
final Symbol rawSymbol;
ObjCProtocolGlobal(String name, this.lookupName, this.loaderName)
: rawSymbol = Symbol('${name}_raw', SymbolKind.field),
super(
originalName: name,
symbol: Symbol(name, SymbolKind.field),
isInternal: true,
);

@override
BindingString toBindingString(Writer w) {
final context = w.context;
final ffi = context.libs.prefix(ffiImport);
final ptrType = PointerType(objCProtocolType).getCType(context);
final getProtocol = ObjCBuiltInFunctions.getProtocol.gen(context);
final s =
'''
@$ffi.Native<$ptrType Function()>(symbol: '$loaderName')
external $ptrType ${rawSymbol.name}();
final $name = $getProtocol("$lookupName", ${rawSymbol.name});
''';
return BindingString(type: BindingStringType.global, string: s);
}

@override
void visitChildren(Visitor visitor) {
super.visitChildren(visitor);
visitor.visit(ffiImport);
visitor.visit(objcPkgImport);
visitor.visit(objCProtocolType);
visitor.visit(rawSymbol);
}
}

enum ObjCMsgSendVariant {
normal(ObjCBuiltInFunctions.msgSendPointer),
stret(ObjCBuiltInFunctions.msgSendStretPointer),
Expand Down
2 changes: 1 addition & 1 deletion pkgs/ffigen/lib/src/code_generator/objc_category.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ObjCCategory extends NoLookUpBinding with ObjCMethods, HasLocalScope {
@override
final Context context;
final ObjCInterface parent;
final ObjCInternalGlobal classObject;
final NoLookUpBinding classObject;

final protocols = <ObjCProtocol>[];

Expand Down
7 changes: 2 additions & 5 deletions pkgs/ffigen/lib/src/code_generator/objc_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ObjCInterface extends BindingType with ObjCMethods, HasLocalScope {
bool filled = false;

final String lookupName;
late final ObjCInternalGlobal classObject;
late final NoLookUpBinding classObject;
late final ObjCInternalGlobal _isKindOfClass;
late final ObjCMsgSendFunc _isKindOfClassMsgSend;
final protocols = <ObjCProtocol>[];
Expand Down Expand Up @@ -46,10 +46,7 @@ class ObjCInterface extends BindingType with ObjCMethods, HasLocalScope {
name ??
originalName,
) {
classObject = ObjCInternalGlobal(
'_class_$originalName',
() => '${ObjCBuiltInFunctions.getClass.gen(context)}("$lookupName")',
);
classObject = ObjCClassGlobal('_class_$originalName', this.lookupName);
_isKindOfClass = context.objCBuiltInFunctions.getSelObject(
'isKindOfClass:',
);
Expand Down
9 changes: 5 additions & 4 deletions pkgs/ffigen/lib/src/code_generator/objc_protocol.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ObjCProtocol extends BindingType with ObjCMethods, HasLocalScope {
final Context context;
final superProtocols = <ObjCProtocol>[];
final String lookupName;
final ObjCInternalGlobal _protocolPointer;
final NoLookUpBinding _protocolPointer;
late final ObjCInternalGlobal _conformsTo;
late final ObjCMsgSendFunc _conformsToMsgSend;
final ApiAvailability apiAvailability;
Expand All @@ -33,10 +33,10 @@ class ObjCProtocol extends BindingType with ObjCMethods, HasLocalScope {
required this.apiAvailability,
required this.context,
}) : lookupName = lookupName ?? originalName,
_protocolPointer = ObjCInternalGlobal(
_protocolPointer = ObjCProtocolGlobal(
'_protocol_$originalName',
() =>
'${ObjCBuiltInFunctions.getProtocol.gen(context)}("$lookupName")',
lookupName ?? originalName,
'_${context.objCBuiltInFunctions.libraryId}_$originalName',
),
super(
name:
Expand Down Expand Up @@ -337,6 +337,7 @@ ${generateInstanceMethodBindings(w, this)}
final mainString =
'''

__attribute__((visibility("default"))) __attribute__((used))
Protocol* _${libraryId}_$originalName(void) { return @protocol($originalName); }
''';

Expand Down
10 changes: 1 addition & 9 deletions pkgs/ffigen/test/example_tests/swift_example_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,7 @@ void main() {
expect(actual, contains('set someField(int value) {'));

// Verify that SwiftClass is loaded using the swift_module prefix.
expect(
actual,
contains(
RegExp(
r'late final _class_SwiftClass.* = '
r'objc.getClass.*\("swift_module\.SwiftClass"\)',
),
),
);
expect(actual, contains(r'OBJC_CLASS_\$_swift_module.SwiftClass'));

return true;
},
Expand Down
22 changes: 20 additions & 2 deletions pkgs/ffigen/test/native_objc_test/arc_test_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,26 @@ extension ArcTestObject$Methods on ArcTestObject {
}
}

late final _class_ArcDtorTestObject = objc.getClass("ArcDtorTestObject");
late final _class_ArcTestObject = objc.getClass("ArcTestObject");
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_ArcDtorTestObject',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_ArcDtorTestObject_raw;
final _class_ArcDtorTestObject = objc.getClass(
"ArcDtorTestObject",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_ArcDtorTestObject_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_ArcTestObject',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_ArcTestObject_raw;
final _class_ArcTestObject = objc.getClass(
"ArcTestObject",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_ArcTestObject_raw,
).cast(),
);
final _objc_msgSend_129vhbw = objc.msgSendPointer
.cast<
ffi.NativeFunction<
Expand Down
11 changes: 10 additions & 1 deletion pkgs/ffigen/test/native_objc_test/bad_method_test_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,16 @@ final class BitField extends ffi.Opaque {}

final class IncompleteStruct extends ffi.Opaque {}

late final _class_BadMethodTestObject = objc.getClass("BadMethodTestObject");
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadMethodTestObject',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadMethodTestObject_raw;
final _class_BadMethodTestObject = objc.getClass(
"BadMethodTestObject",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadMethodTestObject_raw,
).cast(),
);
final _objc_msgSend_151sglz = objc.msgSendPointer
.cast<
ffi.NativeFunction<
Expand Down
109 changes: 98 additions & 11 deletions pkgs/ffigen/test/native_objc_test/bad_override_test_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -879,21 +879,108 @@ extension Triangle$Methods on Triangle {
}
}

late final _class_BadOverrideAunt = objc.getClass("BadOverrideAunt");
late final _class_BadOverrideChild = objc.getClass("BadOverrideChild");
late final _class_BadOverrideGrandchild = objc.getClass(
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadOverrideAunt',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadOverrideAunt_raw;
final _class_BadOverrideAunt = objc.getClass(
"BadOverrideAunt",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadOverrideAunt_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadOverrideChild',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadOverrideChild_raw;
final _class_BadOverrideChild = objc.getClass(
"BadOverrideChild",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadOverrideChild_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadOverrideGrandchild',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadOverrideGrandchild_raw;
final _class_BadOverrideGrandchild = objc.getClass(
"BadOverrideGrandchild",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadOverrideGrandchild_raw,
).cast(),
);
late final _class_BadOverrideGrandparent = objc.getClass(
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadOverrideGrandparent',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadOverrideGrandparent_raw;
final _class_BadOverrideGrandparent = objc.getClass(
"BadOverrideGrandparent",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadOverrideGrandparent_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadOverrideParent',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadOverrideParent_raw;
final _class_BadOverrideParent = objc.getClass(
"BadOverrideParent",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadOverrideParent_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadOverrideSibbling',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadOverrideSibbling_raw;
final _class_BadOverrideSibbling = objc.getClass(
"BadOverrideSibbling",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadOverrideSibbling_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(
symbol: 'OBJC_CLASS_\$_BadOverrideUncle',
)
external ffi.Pointer<objc.ObjCObjectImpl> _class_BadOverrideUncle_raw;
final _class_BadOverrideUncle = objc.getClass(
"BadOverrideUncle",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_BadOverrideUncle_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(symbol: 'OBJC_CLASS_\$_Polygon')
external ffi.Pointer<objc.ObjCObjectImpl> _class_Polygon_raw;
final _class_Polygon = objc.getClass(
"Polygon",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_Polygon_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(symbol: 'OBJC_CLASS_\$_Rectangle')
external ffi.Pointer<objc.ObjCObjectImpl> _class_Rectangle_raw;
final _class_Rectangle = objc.getClass(
"Rectangle",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_Rectangle_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(symbol: 'OBJC_CLASS_\$_Square')
external ffi.Pointer<objc.ObjCObjectImpl> _class_Square_raw;
final _class_Square = objc.getClass(
"Square",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_Square_raw,
).cast(),
);
@ffi.Native<ffi.Pointer<objc.ObjCObjectImpl>>(symbol: 'OBJC_CLASS_\$_Triangle')
external ffi.Pointer<objc.ObjCObjectImpl> _class_Triangle_raw;
final _class_Triangle = objc.getClass(
"Triangle",
() => ffi.Native.addressOf<ffi.Pointer<objc.ObjCObjectImpl>>(
_class_Triangle_raw,
).cast(),
);
late final _class_BadOverrideParent = objc.getClass("BadOverrideParent");
late final _class_BadOverrideSibbling = objc.getClass("BadOverrideSibbling");
late final _class_BadOverrideUncle = objc.getClass("BadOverrideUncle");
late final _class_Polygon = objc.getClass("Polygon");
late final _class_Rectangle = objc.getClass("Rectangle");
late final _class_Square = objc.getClass("Square");
late final _class_Triangle = objc.getClass("Triangle");
final _objc_msgSend_151sglz = objc.msgSendPointer
.cast<
ffi.NativeFunction<
Expand Down
Loading
Loading