Add NSAttributedString for object c binding
// ignore_for_file: avoid_print
import 'dart:io';
import 'package:ffigen/ffigen.dart';
import 'package:logging/logging.dart';
void main() {
final iosSdkPath =
'/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks';
final generator = FfiGenerator(
headers: Headers(
entryPoints: [
// UIKit and PDFKit from real SDK
Uri.file('$iosSdkPath/UIKit.framework/Headers/UIKit.h'),
Uri.file('$iosSdkPath/PDFKit.framework/Headers/PDFKit.h'),
Uri.file('$iosSdkPath/CoreGraphics.framework/Headers/CoreGraphics.h'),
Uri.file('$iosSdkPath/Foundation.framework/Headers/Foundation.h'),
],
),
objectiveC: ObjectiveC(
interfaces: Interfaces(
include: (decl) {
// Include relevant UIKit + PDFKit classes
return [
// UIKit
"UIView", "UILabel", "UIColor", "UIFont", "UIImage", "UIScreen",
"UINavigationController", "UIWindow", "UIViewController",
"UIGraphicsImageRenderer", "UIGraphicsImageRendererContext",
// PDFKit
"PDFDocument", "PDFPage", "PDFAnnotation", "PDFOutline",
].contains(decl.originalName);
},
renameMember: (declaration, member) {
// Handle naming conflicts if any
if (member == 'initWithFrame:primaryAction:') {
return 'initWithFramePrimaryAction';
}
return member;
},
),
),
output: Output(
dartFile: Uri.file('lib/system_bindings.g.dart'),
objectiveCFile: Uri.file('ios/Classes/system_bindings.m'),
format: true,
preamble: '''
// ignore_for_file: unused_element, unused_field, return_of_invalid_type
''',
),
);
generator.generate(
logger: Logger('Bindings')..onRecord.listen((r) => print(r.message)),
);
// Replace many #imports with clean framework imports
final objcFile = File('ios/Classes/system_bindings.m');
var content = objcFile.readAsStringSync();
content = content.replaceAllMapped(
RegExp(r'#import "(.*\.h)"\n'),
(match) => '',
);
content = '''#import <UIKit/UIKit.h>
#import <PDFKit/PDFKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
$content''';
objcFile.writeAsStringSync(content);
print('✅ Generated bindings successfully at lib/system_bindings.g.dart');
}
all binding are generated but NSAtttributedString in missing in Objectc also enums values are also not converted to int automatically
Are you asking for NSAttributedString to be added to the package:objective_c bindings? Or are you saying that you expect NSAttributedString to be part of your bindings but it isn't?
enums values are also not converted to int automatically
Not sure what you mean by this. Could you explain what behaviour you're expecting, and what you're seeing?
Also, what version of FFIgen are you using? There have been some updates to how ObjC enums are code genned in v20, but it's only in prerelease atm.
@liamappelbe
objective_c 9.0.0-dev NSAttributedString was not exported from the binding previously, but after running with the main branch, it is now accessible. However, there is an issue with the main branch: the enum conversions have changed. In previous versions of ffigen, enums were converted with their values, but now they are converted to sealed classes. The generated binding contains errors because the native functions expect int values, but the binding is providing sealed class references. Additionally, some protocols are not excluded from generate_file.m.
I can't really help you if you give me so little information. I'm still not sure what version of ffigen you're using (you gave me the objective_c version, not ffigen), but I'll assume you're using the v20 prerelease.
There are 2 kinds of enum in ObjC, NS_ENUM and NS_OPTION, with the difference being that NS_OPTIONs are designed to be bitwise combined. In ffigen v20 we detect this difference and generate a Dart enum for NS_ENUM and an int for NS_OPTION. So presumably your bindings are declaring a NS_ENUM, but you haven't given me any input or output files, so I'm just guessing.
If you want an NS_ENUM to generate as ints, you can use FfiGenerator.enums.style.
Additionally, some protocols are not excluded from
generate_file.m.
You'll need to give me more info if you want me to help. What are your inputs and outputs, and what's the expected output.
I can't really help you if you give me so little information. I'm still not sure what version of ffigen you're using (you gave me the
objective_cversion, not ffigen), but I'll assume you're using the v20 prerelease.There are 2 kinds of enum in ObjC,
NS_ENUMandNS_OPTION, with the difference being thatNS_OPTIONs are designed to be bitwise combined. In ffigen v20 we detect this difference and generate a DartenumforNS_ENUMand an int forNS_OPTION. So presumably your bindings are declaring aNS_ENUM, but you haven't given me any input or output files, so I'm just guessing.If you want an
NS_ENUMto generate as ints, you can useFfiGenerator.enums.style.Additionally, some protocols are not excluded from
generate_file.m.You'll need to give me more info if you want me to help. What are your inputs and outputs, and what's the expected output.
@liamappelbe pdf_compressor.zip that is sample you can check the bindings also how i can exclude the macos protocols in that ?
Which protocols did you want to exclude? I see a bunch of stubbed protocols. These stubs are generated because other APIs depend on them. In a sense, stubs are already excluded, since we only generate a minimal amount of code for them to get the bindings to compile.
For example, the PDFDocumentDelegate stub exists because it's the return type of PDFDocument.delegate. To avoid generating these stubs entirely you'd need to filter out any method that depends on them, like using method filtering to remove PDFDocument.delegate. And even if you did that you'd still get stubs for all the protocols that your interfaces implement.
I recommend you just ignore the stubs. Removing them from the bindings is difficult, and pointless. These stubs aren't causing any problems.
@liamappelbe, what about sealed classes that should be generated as enums because native method accepts values like int and sealed classes cannot be directly pass in that function? That's why the analyzer is showing an error on that
@liamappelbe, what about sealed classes that should be generated as enums because native method accepts values like int and sealed classes cannot be directly pass in that function? That's why the analyzer is showing an error on that
I need more details. Can you give me an example of the problematic code? Post the analyzer error message? Create a minimal repro example? Did you try the FfiGenerator.enums.style suggestion I gave earlier?
@liamappelbe, what about sealed classes that should be generated as enums because native method accepts values like int and sealed classes cannot be directly pass in that function? That's why the analyzer is showing an error on that
I need more details. Can you give me an example of the problematic code? Post the analyzer error message? Create a minimal repro example? Did you try the
FfiGenerator.enums.stylesuggestion I gave earlier?
can you provide sample how to do that?
@liamappelbe can proivde some sample how i can set FfiGenerator.enums.style
@liamappelbe can proivde some sample how i can set
FfiGenerator.enums.style
Set the enums options in your FfiGenerator constructor. Something like this:
FfiGenerator(
...
enums: Enums(
style: (Declaration declaration, EnumStyle? suggestedStyle) => EnumStyle.intConstants,
),
)
Hi @liamappelbe, thanks for your guidance. I'm currently updating maplibre to ffigen 20 and noticed that EnumStyle is not exported by the package.
I worked around that issue with a src import for now.
import 'package:ffigen/ffigen.dart';
import 'package:ffigen/src/config_provider/config.dart' show EnumStyle;
edit: Found a few more missing exports, opened https://github.com/dart-lang/native/issues/2765 for it.