[ffigen] Make all NSObject references nullable in the generated dart bindings. (#339)

diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart
index 65536ff..c7cdbea 100644
--- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart
+++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart
@@ -69,8 +69,10 @@
       if (isStatic) {
         stringParams.add('${w.className} _lib');
       }
-      stringParams.addAll(
-          params.map((p) => '${_getConvertedType(p.type, w, name)} ${p.name}'));
+      stringParams.addAll(params.map((p) =>
+          (_getConvertedType(p.type, w, name) +
+              (p.isNullable ? "? " : " ") +
+              p.name)));
       return '(' + stringParams.join(", ") + ')';
     }
 
@@ -170,7 +172,7 @@
       s.write(isStatic ? '_lib.${_classObject.name}' : '_id');
       s.write(', _lib.${m.selObject!.name}');
       for (final p in m.params) {
-        s.write(', ${_doArgConversion(p.type, p.name)}');
+        s.write(', ${_doArgConversion(p)}');
       }
       s.write(');\n');
       if (convertReturn) {
@@ -304,11 +306,17 @@
     return type.getDartType(w);
   }
 
-  String _doArgConversion(Type type, String value) {
-    if (type is ObjCInterface || _isObject(type) || _isInstanceType(type)) {
-      return '$value._id';
+  String _doArgConversion(ObjCMethodParam arg) {
+    if (arg.type is ObjCInterface ||
+        _isObject(arg.type) ||
+        _isInstanceType(arg.type)) {
+      if (arg.isNullable) {
+        return '${arg.name}?._id ?? ffi.nullptr';
+      } else {
+        return '${arg.name}._id';
+      }
     }
-    return value;
+    return arg.name;
   }
 
   String _doReturnConversion(
@@ -395,5 +403,6 @@
 class ObjCMethodParam {
   final Type type;
   final String name;
-  ObjCMethodParam(this.type, this.name);
+  final bool isNullable;
+  ObjCMethodParam(this.type, this.name, {this.isNullable = false});
 }
diff --git a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
index 0075ca9..9191f67 100644
--- a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
+++ b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
@@ -829,6 +829,21 @@
   late final _clang_Type_getNamedType =
       _clang_Type_getNamedTypePtr.asFunction<CXType Function(CXType)>();
 
+  /// Retrieve the nullability kind of a pointer type.
+  int clang_Type_getNullability(
+    CXType T,
+  ) {
+    return _clang_Type_getNullability(
+      T,
+    );
+  }
+
+  late final _clang_Type_getNullabilityPtr =
+      _lookup<ffi.NativeFunction<ffi.Int32 Function(CXType)>>(
+          'clang_Type_getNullability');
+  late final _clang_Type_getNullability =
+      _clang_Type_getNullabilityPtr.asFunction<int Function(CXType)>();
+
   /// Return the alignment of a type in bytes as per C++[expr.alignof]
   /// standard.
   ///
@@ -2448,6 +2463,23 @@
   external ffi.Array<ffi.Pointer<ffi.Void>> data;
 }
 
+abstract class CXTypeNullabilityKind {
+  /// Values of this type can never be null.
+  static const int CXTypeNullability_NonNull = 0;
+
+  /// Values of this type can be null.
+  static const int CXTypeNullability_Nullable = 1;
+
+  /// Whether values of this type can be null is (explicitly)
+  /// unspecified. This captures a (fairly rare) case where we
+  /// can't conclude anything about the nullability of the type even
+  /// though it has been considered.
+  static const int CXTypeNullability_Unspecified = 2;
+
+  /// Nullability is not applicable to this type.
+  static const int CXTypeNullability_Invalid = 3;
+}
+
 /// Describes how the traversal of the children of a particular
 /// cursor should proceed after visiting a particular child cursor.
 ///
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart
index 6d90c3d..c9451cf 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart
@@ -211,9 +211,25 @@
 }
 
 void _parseMethodParam(clang_types.CXCursor cursor) {
+  /*
+  TODO(#334): Change this to use:
+  
+  clang.clang_Type_getNullability(cursor.type()) ==
+      clang_types.CXTypeNullabilityKind.CXTypeNullability_Nullable;
+
+  NOTE: This will only work with the
+
+    clang_types
+      .CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes
+
+  option set.
+  */
+  final isNullable =
+      cursor.type().kind == clang_types.CXTypeKind.CXType_ObjCObjectPointer;
   final name = cursor.spelling();
   final type = cursor.type().toCodeGenType();
   _logger.fine(
       '           >> Parameter: $type $name ${cursor.completeStringRepr()}');
-  _methodStack.top.method.params.add(ObjCMethodParam(type, name));
+  _methodStack.top.method.params
+      .add(ObjCMethodParam(type, name, isNullable: isNullable));
 }
diff --git a/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_config_bindings.dart b/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_config_bindings.dart
index e647802..cedcffe 100644
--- a/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_config_bindings.dart
+++ b/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_config_bindings.dart
@@ -521,9 +521,9 @@
         _lib._sel_instancesRespondToSelector_1, aSelector);
   }
 
-  static bool conformsToProtocol(NativeLibrary _lib, NSObject protocol) {
-    return _lib._objc_msgSend_4(
-        _lib._class_NSObject1, _lib._sel_conformsToProtocol_1, protocol._id);
+  static bool conformsToProtocol(NativeLibrary _lib, NSObject? protocol) {
+    return _lib._objc_msgSend_4(_lib._class_NSObject1,
+        _lib._sel_conformsToProtocol_1, protocol?._id ?? ffi.nullptr);
   }
 
   IMP methodForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -546,8 +546,9 @@
     return NSObject._(_ret, _lib);
   }
 
-  void forwardInvocation(NSObject anInvocation) {
-    _lib._objc_msgSend_8(_id, _lib._sel_forwardInvocation_1, anInvocation._id);
+  void forwardInvocation(NSObject? anInvocation) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_forwardInvocation_1, anInvocation?._id ?? ffi.nullptr);
   }
 
   NSMethodSignature methodSignatureForSelector(ffi.Pointer<ObjCSel> aSelector) {
diff --git a/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_interface_bindings.dart b/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_interface_bindings.dart
index 551e558..efb1b93 100644
--- a/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_interface_bindings.dart
+++ b/pkgs/ffigen/test/header_parser_tests/expected_bindings/_expected_objc_interface_bindings.dart
@@ -562,9 +562,9 @@
     return Foo._(_ret, _lib);
   }
 
-  int anInstanceMethod_withOtherArg(NSObject someArg, NSObject otherArg) {
+  int anInstanceMethod_withOtherArg(NSObject? someArg, NSObject? otherArg) {
     return _lib._objc_msgSend_18(_id, _lib._sel_anInstanceMethod_withOtherArg_1,
-        someArg._id, otherArg._id);
+        someArg?._id ?? ffi.nullptr, otherArg?._id ?? ffi.nullptr);
   }
 
   static Foo new1(NativeLibrary _lib) {
@@ -655,9 +655,9 @@
         _lib._sel_instancesRespondToSelector_1, aSelector);
   }
 
-  static bool conformsToProtocol(NativeLibrary _lib, NSObject protocol) {
-    return _lib._objc_msgSend_4(
-        _lib._class_NSObject1, _lib._sel_conformsToProtocol_1, protocol._id);
+  static bool conformsToProtocol(NativeLibrary _lib, NSObject? protocol) {
+    return _lib._objc_msgSend_4(_lib._class_NSObject1,
+        _lib._sel_conformsToProtocol_1, protocol?._id ?? ffi.nullptr);
   }
 
   IMP methodForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -680,8 +680,9 @@
     return NSObject._(_ret, _lib);
   }
 
-  void forwardInvocation(NSObject anInvocation) {
-    _lib._objc_msgSend_8(_id, _lib._sel_forwardInvocation_1, anInvocation._id);
+  void forwardInvocation(NSObject? anInvocation) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_forwardInvocation_1, anInvocation?._id ?? ffi.nullptr);
   }
 
   NSMethodSignature methodSignatureForSelector(ffi.Pointer<ObjCSel> aSelector) {
diff --git a/pkgs/ffigen/test/native_objc_test/method_bindings.dart b/pkgs/ffigen/test/native_objc_test/method_bindings.dart
index 2ebbe59..fc3bd60 100644
--- a/pkgs/ffigen/test/native_objc_test/method_bindings.dart
+++ b/pkgs/ffigen/test/native_objc_test/method_bindings.dart
@@ -836,9 +836,9 @@
   }
 
   static bool conformsToProtocol(
-      MethodTestObjCLibrary _lib, NSObject protocol) {
-    return _lib._objc_msgSend_4(
-        _lib._class_NSObject1, _lib._sel_conformsToProtocol_1, protocol._id);
+      MethodTestObjCLibrary _lib, NSObject? protocol) {
+    return _lib._objc_msgSend_4(_lib._class_NSObject1,
+        _lib._sel_conformsToProtocol_1, protocol?._id ?? ffi.nullptr);
   }
 
   IMP methodForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -861,8 +861,9 @@
     return NSObject._(_ret, _lib);
   }
 
-  void forwardInvocation(NSObject anInvocation) {
-    _lib._objc_msgSend_8(_id, _lib._sel_forwardInvocation_1, anInvocation._id);
+  void forwardInvocation(NSObject? anInvocation) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_forwardInvocation_1, anInvocation?._id ?? ffi.nullptr);
   }
 
   NSMethodSignature methodSignatureForSelector(ffi.Pointer<ObjCSel> aSelector) {
diff --git a/pkgs/ffigen/test/native_objc_test/native_objc_test_bindings.dart b/pkgs/ffigen/test/native_objc_test/native_objc_test_bindings.dart
index 5b9e98f..b6edcc8 100644
--- a/pkgs/ffigen/test/native_objc_test/native_objc_test_bindings.dart
+++ b/pkgs/ffigen/test/native_objc_test/native_objc_test_bindings.dart
@@ -1170,9 +1170,9 @@
     return Foo._(_ret, _lib);
   }
 
-  int multiply_withOtherFoo(bool useIntVals, NSObject other) {
-    return _lib._objc_msgSend_20(
-        _id, _lib._sel_multiply_withOtherFoo_1, useIntVals, other._id);
+  int multiply_withOtherFoo(bool useIntVals, NSObject? other) {
+    return _lib._objc_msgSend_20(_id, _lib._sel_multiply_withOtherFoo_1,
+        useIntVals, other?._id ?? ffi.nullptr);
   }
 
   void setDoubleVal(double x) {
@@ -1268,9 +1268,9 @@
         _lib._sel_instancesRespondToSelector_1, aSelector);
   }
 
-  static bool conformsToProtocol(NativeObjCLibrary _lib, NSObject protocol) {
-    return _lib._objc_msgSend_4(
-        _lib._class_NSObject1, _lib._sel_conformsToProtocol_1, protocol._id);
+  static bool conformsToProtocol(NativeObjCLibrary _lib, NSObject? protocol) {
+    return _lib._objc_msgSend_4(_lib._class_NSObject1,
+        _lib._sel_conformsToProtocol_1, protocol?._id ?? ffi.nullptr);
   }
 
   IMP methodForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -1293,8 +1293,9 @@
     return NSObject._(_ret, _lib);
   }
 
-  void forwardInvocation(NSObject anInvocation) {
-    _lib._objc_msgSend_8(_id, _lib._sel_forwardInvocation_1, anInvocation._id);
+  void forwardInvocation(NSObject? anInvocation) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_forwardInvocation_1, anInvocation?._id ?? ffi.nullptr);
   }
 
   NSMethodSignature methodSignatureForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -1410,9 +1411,9 @@
     return NSString._(_ret, _lib);
   }
 
-  NSString initWithCoder(NSObject coder) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithCoder_1, coder._id);
+  NSString initWithCoder(NSObject? coder) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithCoder_1, coder?._id ?? ffi.nullptr);
     return NSString._(_ret, _lib);
   }
 
diff --git a/pkgs/ffigen/test/native_objc_test/nullable_bindings.dart b/pkgs/ffigen/test/native_objc_test/nullable_bindings.dart
new file mode 100644
index 0000000..2350bb5
--- /dev/null
+++ b/pkgs/ffigen/test/native_objc_test/nullable_bindings.dart
@@ -0,0 +1,1230 @@
+// ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+//
+// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+import 'package:ffi/ffi.dart' as pkg_ffi;
+
+/// Tests calling Objective-C methods
+class NullableTestObjCLibrary {
+  /// Holds the symbol lookup function.
+  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
+      _lookup;
+
+  /// The symbols are looked up in [dynamicLibrary].
+  NullableTestObjCLibrary(ffi.DynamicLibrary dynamicLibrary)
+      : _lookup = dynamicLibrary.lookup;
+
+  /// The symbols are looked up with [lookup].
+  NullableTestObjCLibrary.fromLookup(
+      ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
+          lookup)
+      : _lookup = lookup;
+
+  late final ffi.Pointer<ffi.Double> _NSFoundationVersionNumber =
+      _lookup<ffi.Double>('NSFoundationVersionNumber');
+
+  double get NSFoundationVersionNumber => _NSFoundationVersionNumber.value;
+
+  set NSFoundationVersionNumber(double value) =>
+      _NSFoundationVersionNumber.value = value;
+
+  late final ffi.Pointer<NSInteger> _NSNotFound =
+      _lookup<NSInteger>('NSNotFound');
+
+  int get NSNotFound => _NSNotFound.value;
+
+  set NSNotFound(int value) => _NSNotFound.value = value;
+
+  late final ffi.Pointer<ffi.Double> _kCFCoreFoundationVersionNumber =
+      _lookup<ffi.Double>('kCFCoreFoundationVersionNumber');
+
+  double get kCFCoreFoundationVersionNumber =>
+      _kCFCoreFoundationVersionNumber.value;
+
+  set kCFCoreFoundationVersionNumber(double value) =>
+      _kCFCoreFoundationVersionNumber.value = value;
+
+  late final ffi.Pointer<CFIndex> _kCFNotFound =
+      _lookup<CFIndex>('kCFNotFound');
+
+  int get kCFNotFound => _kCFNotFound.value;
+
+  set kCFNotFound(int value) => _kCFNotFound.value = value;
+
+  late final ffi.Pointer<CFNullRef> _kCFNull = _lookup<CFNullRef>('kCFNull');
+
+  CFNullRef get kCFNull => _kCFNull.value;
+
+  set kCFNull(CFNullRef value) => _kCFNull.value = value;
+
+  late final ffi.Pointer<CFAllocatorRef> _kCFAllocatorDefault =
+      _lookup<CFAllocatorRef>('kCFAllocatorDefault');
+
+  CFAllocatorRef get kCFAllocatorDefault => _kCFAllocatorDefault.value;
+
+  set kCFAllocatorDefault(CFAllocatorRef value) =>
+      _kCFAllocatorDefault.value = value;
+
+  late final ffi.Pointer<CFAllocatorRef> _kCFAllocatorSystemDefault =
+      _lookup<CFAllocatorRef>('kCFAllocatorSystemDefault');
+
+  CFAllocatorRef get kCFAllocatorSystemDefault =>
+      _kCFAllocatorSystemDefault.value;
+
+  set kCFAllocatorSystemDefault(CFAllocatorRef value) =>
+      _kCFAllocatorSystemDefault.value = value;
+
+  late final ffi.Pointer<CFAllocatorRef> _kCFAllocatorMalloc =
+      _lookup<CFAllocatorRef>('kCFAllocatorMalloc');
+
+  CFAllocatorRef get kCFAllocatorMalloc => _kCFAllocatorMalloc.value;
+
+  set kCFAllocatorMalloc(CFAllocatorRef value) =>
+      _kCFAllocatorMalloc.value = value;
+
+  late final ffi.Pointer<CFAllocatorRef> _kCFAllocatorMallocZone =
+      _lookup<CFAllocatorRef>('kCFAllocatorMallocZone');
+
+  CFAllocatorRef get kCFAllocatorMallocZone => _kCFAllocatorMallocZone.value;
+
+  set kCFAllocatorMallocZone(CFAllocatorRef value) =>
+      _kCFAllocatorMallocZone.value = value;
+
+  late final ffi.Pointer<CFAllocatorRef> _kCFAllocatorNull =
+      _lookup<CFAllocatorRef>('kCFAllocatorNull');
+
+  CFAllocatorRef get kCFAllocatorNull => _kCFAllocatorNull.value;
+
+  set kCFAllocatorNull(CFAllocatorRef value) => _kCFAllocatorNull.value = value;
+
+  late final ffi.Pointer<CFAllocatorRef> _kCFAllocatorUseContext =
+      _lookup<CFAllocatorRef>('kCFAllocatorUseContext');
+
+  CFAllocatorRef get kCFAllocatorUseContext => _kCFAllocatorUseContext.value;
+
+  set kCFAllocatorUseContext(CFAllocatorRef value) =>
+      _kCFAllocatorUseContext.value = value;
+
+  ffi.Pointer<ObjCSel> _registerName1(String name) {
+    final cstr = name.toNativeUtf8();
+    final sel = _sel_registerName(cstr.cast());
+    pkg_ffi.calloc.free(cstr);
+    return sel;
+  }
+
+  ffi.Pointer<ObjCSel> _sel_registerName(
+    ffi.Pointer<pkg_ffi.Char> str,
+  ) {
+    return __sel_registerName(
+      str,
+    );
+  }
+
+  late final __sel_registerNamePtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ObjCSel> Function(
+              ffi.Pointer<pkg_ffi.Char>)>>('sel_registerName');
+  late final __sel_registerName = __sel_registerNamePtr
+      .asFunction<ffi.Pointer<ObjCSel> Function(ffi.Pointer<pkg_ffi.Char>)>();
+
+  ffi.Pointer<ObjCObject> _getClass1(String name) {
+    final cstr = name.toNativeUtf8();
+    final clazz = _objc_getClass(cstr.cast());
+    pkg_ffi.calloc.free(cstr);
+    return clazz;
+  }
+
+  ffi.Pointer<ObjCObject> _objc_getClass(
+    ffi.Pointer<pkg_ffi.Char> str,
+  ) {
+    return __objc_getClass(
+      str,
+    );
+  }
+
+  late final __objc_getClassPtr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ObjCObject> Function(
+              ffi.Pointer<pkg_ffi.Char>)>>('objc_getClass');
+  late final __objc_getClass = __objc_getClassPtr.asFunction<
+      ffi.Pointer<ObjCObject> Function(ffi.Pointer<pkg_ffi.Char>)>();
+
+  late final ffi.Pointer<ObjCObject> _class_NullableInterface1 =
+      _getClass1("NullableInterface");
+  late final ffi.Pointer<ObjCObject> _class_NSObject1 = _getClass1("NSObject");
+  late final ffi.Pointer<ObjCSel> _sel_load1 = _registerName1("load");
+  void _objc_msgSend_0(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+  ) {
+    return __objc_msgSend_0(
+      obj,
+      sel,
+    );
+  }
+
+  late final __objc_msgSend_0Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Void Function(
+              ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_0 = __objc_msgSend_0Ptr.asFunction<
+      void Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_initialize1 =
+      _registerName1("initialize");
+  late final ffi.Pointer<ObjCSel> _sel_init1 = _registerName1("init");
+  instancetype _objc_msgSend_1(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+  ) {
+    return __objc_msgSend_1(
+      obj,
+      sel,
+    );
+  }
+
+  late final __objc_msgSend_1Ptr = _lookup<
+      ffi.NativeFunction<
+          instancetype Function(
+              ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_1 = __objc_msgSend_1Ptr.asFunction<
+      instancetype Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_new1 = _registerName1("new");
+  late final ffi.Pointer<ObjCSel> _sel_allocWithZone_1 =
+      _registerName1("allocWithZone:");
+  instancetype _objc_msgSend_2(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<_NSZone> zone,
+  ) {
+    return __objc_msgSend_2(
+      obj,
+      sel,
+      zone,
+    );
+  }
+
+  late final __objc_msgSend_2Ptr = _lookup<
+      ffi.NativeFunction<
+          instancetype Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+              ffi.Pointer<_NSZone>)>>('objc_msgSend');
+  late final __objc_msgSend_2 = __objc_msgSend_2Ptr.asFunction<
+      instancetype Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+          ffi.Pointer<_NSZone>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_alloc1 = _registerName1("alloc");
+  late final ffi.Pointer<ObjCSel> _sel_dealloc1 = _registerName1("dealloc");
+  late final ffi.Pointer<ObjCSel> _sel_finalize1 = _registerName1("finalize");
+  late final ffi.Pointer<ObjCSel> _sel_copy1 = _registerName1("copy");
+  late final ffi.Pointer<ObjCSel> _sel_mutableCopy1 =
+      _registerName1("mutableCopy");
+  late final ffi.Pointer<ObjCSel> _sel_copyWithZone_1 =
+      _registerName1("copyWithZone:");
+  late final ffi.Pointer<ObjCSel> _sel_mutableCopyWithZone_1 =
+      _registerName1("mutableCopyWithZone:");
+  late final ffi.Pointer<ObjCSel> _sel_instancesRespondToSelector_1 =
+      _registerName1("instancesRespondToSelector:");
+  bool _objc_msgSend_3(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<ObjCSel> aSelector,
+  ) {
+    return __objc_msgSend_3(
+          obj,
+          sel,
+          aSelector,
+        ) !=
+        0;
+  }
+
+  late final __objc_msgSend_3Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint8 Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+              ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_3 = __objc_msgSend_3Ptr.asFunction<
+      int Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+          ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_conformsToProtocol_1 =
+      _registerName1("conformsToProtocol:");
+  bool _objc_msgSend_4(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<ObjCObject> protocol,
+  ) {
+    return __objc_msgSend_4(
+          obj,
+          sel,
+          protocol,
+        ) !=
+        0;
+  }
+
+  late final __objc_msgSend_4Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint8 Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+              ffi.Pointer<ObjCObject>)>>('objc_msgSend');
+  late final __objc_msgSend_4 = __objc_msgSend_4Ptr.asFunction<
+      int Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+          ffi.Pointer<ObjCObject>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_methodForSelector_1 =
+      _registerName1("methodForSelector:");
+  IMP _objc_msgSend_5(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<ObjCSel> aSelector,
+  ) {
+    return __objc_msgSend_5(
+      obj,
+      sel,
+      aSelector,
+    );
+  }
+
+  late final __objc_msgSend_5Ptr = _lookup<
+      ffi.NativeFunction<
+          IMP Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+              ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_5 = __objc_msgSend_5Ptr.asFunction<
+      IMP Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+          ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_instanceMethodForSelector_1 =
+      _registerName1("instanceMethodForSelector:");
+  late final ffi.Pointer<ObjCSel> _sel_doesNotRecognizeSelector_1 =
+      _registerName1("doesNotRecognizeSelector:");
+  void _objc_msgSend_6(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<ObjCSel> aSelector,
+  ) {
+    return __objc_msgSend_6(
+      obj,
+      sel,
+      aSelector,
+    );
+  }
+
+  late final __objc_msgSend_6Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+              ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_6 = __objc_msgSend_6Ptr.asFunction<
+      void Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+          ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_forwardingTargetForSelector_1 =
+      _registerName1("forwardingTargetForSelector:");
+  ffi.Pointer<ObjCObject> _objc_msgSend_7(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<ObjCSel> aSelector,
+  ) {
+    return __objc_msgSend_7(
+      obj,
+      sel,
+      aSelector,
+    );
+  }
+
+  late final __objc_msgSend_7Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ObjCObject> Function(ffi.Pointer<ObjCObject>,
+              ffi.Pointer<ObjCSel>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_7 = __objc_msgSend_7Ptr.asFunction<
+      ffi.Pointer<ObjCObject> Function(ffi.Pointer<ObjCObject>,
+          ffi.Pointer<ObjCSel>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_forwardInvocation_1 =
+      _registerName1("forwardInvocation:");
+  void _objc_msgSend_8(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<ObjCObject> anInvocation,
+  ) {
+    return __objc_msgSend_8(
+      obj,
+      sel,
+      anInvocation,
+    );
+  }
+
+  late final __objc_msgSend_8Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Void Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+              ffi.Pointer<ObjCObject>)>>('objc_msgSend');
+  late final __objc_msgSend_8 = __objc_msgSend_8Ptr.asFunction<
+      void Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>,
+          ffi.Pointer<ObjCObject>)>();
+
+  late final ffi.Pointer<ObjCObject> _class_NSMethodSignature1 =
+      _getClass1("NSMethodSignature");
+  late final ffi.Pointer<ObjCSel> _sel_methodSignatureForSelector_1 =
+      _registerName1("methodSignatureForSelector:");
+  ffi.Pointer<ObjCObject> _objc_msgSend_9(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<ObjCSel> aSelector,
+  ) {
+    return __objc_msgSend_9(
+      obj,
+      sel,
+      aSelector,
+    );
+  }
+
+  late final __objc_msgSend_9Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ObjCObject> Function(ffi.Pointer<ObjCObject>,
+              ffi.Pointer<ObjCSel>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_9 = __objc_msgSend_9Ptr.asFunction<
+      ffi.Pointer<ObjCObject> Function(ffi.Pointer<ObjCObject>,
+          ffi.Pointer<ObjCSel>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_instanceMethodSignatureForSelector_1 =
+      _registerName1("instanceMethodSignatureForSelector:");
+  late final ffi.Pointer<ObjCSel> _sel_allowsWeakReference1 =
+      _registerName1("allowsWeakReference");
+  bool _objc_msgSend_10(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+  ) {
+    return __objc_msgSend_10(
+          obj,
+          sel,
+        ) !=
+        0;
+  }
+
+  late final __objc_msgSend_10Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Uint8 Function(
+              ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_10 = __objc_msgSend_10Ptr.asFunction<
+      int Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_retainWeakReference1 =
+      _registerName1("retainWeakReference");
+  late final ffi.Pointer<ObjCSel> _sel_isSubclassOfClass_1 =
+      _registerName1("isSubclassOfClass:");
+  late final ffi.Pointer<ObjCSel> _sel_resolveClassMethod_1 =
+      _registerName1("resolveClassMethod:");
+  late final ffi.Pointer<ObjCSel> _sel_resolveInstanceMethod_1 =
+      _registerName1("resolveInstanceMethod:");
+  late final ffi.Pointer<ObjCSel> _sel_hash1 = _registerName1("hash");
+  int _objc_msgSend_11(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+  ) {
+    return __objc_msgSend_11(
+      obj,
+      sel,
+    );
+  }
+
+  late final __objc_msgSend_11Ptr = _lookup<
+      ffi.NativeFunction<
+          NSUInteger Function(
+              ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_11 = __objc_msgSend_11Ptr.asFunction<
+      int Function(ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_superclass1 =
+      _registerName1("superclass");
+  late final ffi.Pointer<ObjCSel> _sel_class1 = _registerName1("class");
+  late final ffi.Pointer<ObjCObject> _class_NSString1 = _getClass1("NSString");
+  late final ffi.Pointer<ObjCSel> _sel_stringWithCString_encoding_1 =
+      _registerName1("stringWithCString:encoding:");
+  ffi.Pointer<ObjCObject> _objc_msgSend_12(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+    ffi.Pointer<pkg_ffi.Char> cString,
+    int enc,
+  ) {
+    return __objc_msgSend_12(
+      obj,
+      sel,
+      cString,
+      enc,
+    );
+  }
+
+  late final __objc_msgSend_12Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ObjCObject> Function(
+              ffi.Pointer<ObjCObject>,
+              ffi.Pointer<ObjCSel>,
+              ffi.Pointer<pkg_ffi.Char>,
+              pkg_ffi.UnsignedInt)>>('objc_msgSend');
+  late final __objc_msgSend_12 = __objc_msgSend_12Ptr.asFunction<
+      ffi.Pointer<ObjCObject> Function(ffi.Pointer<ObjCObject>,
+          ffi.Pointer<ObjCSel>, ffi.Pointer<pkg_ffi.Char>, int)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_UTF8String1 =
+      _registerName1("UTF8String");
+  ffi.Pointer<pkg_ffi.Char> _objc_msgSend_13(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+  ) {
+    return __objc_msgSend_13(
+      obj,
+      sel,
+    );
+  }
+
+  late final __objc_msgSend_13Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<pkg_ffi.Char> Function(
+              ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_13 = __objc_msgSend_13Ptr.asFunction<
+      ffi.Pointer<pkg_ffi.Char> Function(
+          ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_description1 =
+      _registerName1("description");
+  ffi.Pointer<ObjCObject> _objc_msgSend_14(
+    ffi.Pointer<ObjCObject> obj,
+    ffi.Pointer<ObjCSel> sel,
+  ) {
+    return __objc_msgSend_14(
+      obj,
+      sel,
+    );
+  }
+
+  late final __objc_msgSend_14Ptr = _lookup<
+      ffi.NativeFunction<
+          ffi.Pointer<ObjCObject> Function(
+              ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>>('objc_msgSend');
+  late final __objc_msgSend_14 = __objc_msgSend_14Ptr.asFunction<
+      ffi.Pointer<ObjCObject> Function(
+          ffi.Pointer<ObjCObject>, ffi.Pointer<ObjCSel>)>();
+
+  late final ffi.Pointer<ObjCSel> _sel_debugDescription1 =
+      _registerName1("debugDescription");
+  late final ffi.Pointer<ObjCSel> _sel_isNullWithNullableNSObjectArg_1 =
+      _registerName1("isNullWithNullableNSObjectArg:");
+  late final ffi.Pointer<ObjCSel> _sel_isNullWithNotNullableNSObjectPtrArg_1 =
+      _registerName1("isNullWithNotNullableNSObjectPtrArg:");
+}
+
+abstract class NSComparisonResult {
+  static const int NSOrderedAscending = -1;
+  static const int NSOrderedSame = 0;
+  static const int NSOrderedDescending = 1;
+}
+
+abstract class NSEnumerationOptions {
+  static const int NSEnumerationConcurrent = 1;
+  static const int NSEnumerationReverse = 2;
+}
+
+abstract class NSSortOptions {
+  static const int NSSortConcurrent = 1;
+  static const int NSSortStable = 16;
+}
+
+abstract class NSQualityOfService {
+  static const int NSQualityOfServiceUserInteractive = 33;
+  static const int NSQualityOfServiceUserInitiated = 25;
+  static const int NSQualityOfServiceUtility = 17;
+  static const int NSQualityOfServiceBackground = 9;
+  static const int NSQualityOfServiceDefault = -1;
+}
+
+typedef NSInteger = pkg_ffi.Long;
+
+class __CFString extends ffi.Opaque {}
+
+abstract class CFComparisonResult {
+  static const int kCFCompareLessThan = -1;
+  static const int kCFCompareEqualTo = 0;
+  static const int kCFCompareGreaterThan = 1;
+}
+
+typedef CFIndex = pkg_ffi.Long;
+
+class CFRange extends ffi.Struct {
+  @CFIndex()
+  external int location;
+
+  @CFIndex()
+  external int length;
+}
+
+class __CFNull extends ffi.Opaque {}
+
+typedef CFNullRef = ffi.Pointer<__CFNull>;
+
+class __CFAllocator extends ffi.Opaque {}
+
+typedef CFAllocatorRef = ffi.Pointer<__CFAllocator>;
+
+class CFAllocatorContext extends ffi.Struct {
+  @CFIndex()
+  external int version;
+
+  external ffi.Pointer<ffi.Void> info;
+
+  external CFAllocatorRetainCallBack retain;
+
+  external CFAllocatorReleaseCallBack release;
+
+  external CFAllocatorCopyDescriptionCallBack copyDescription;
+
+  external CFAllocatorAllocateCallBack allocate;
+
+  external CFAllocatorReallocateCallBack reallocate;
+
+  external CFAllocatorDeallocateCallBack deallocate;
+
+  external CFAllocatorPreferredSizeCallBack preferredSize;
+}
+
+typedef CFAllocatorRetainCallBack = ffi.Pointer<
+    ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>>;
+typedef CFAllocatorReleaseCallBack
+    = ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>;
+typedef CFAllocatorCopyDescriptionCallBack = ffi
+    .Pointer<ffi.NativeFunction<CFStringRef Function(ffi.Pointer<ffi.Void>)>>;
+typedef CFStringRef = ffi.Pointer<__CFString>;
+typedef CFAllocatorAllocateCallBack = ffi.Pointer<
+    ffi.NativeFunction<
+        ffi.Pointer<ffi.Void> Function(
+            CFIndex, CFOptionFlags, ffi.Pointer<ffi.Void>)>>;
+typedef CFOptionFlags = pkg_ffi.UnsignedLong;
+typedef CFAllocatorReallocateCallBack = ffi.Pointer<
+    ffi.NativeFunction<
+        ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>, CFIndex,
+            CFOptionFlags, ffi.Pointer<ffi.Void>)>>;
+typedef CFAllocatorDeallocateCallBack = ffi.Pointer<
+    ffi.NativeFunction<
+        ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>;
+typedef CFAllocatorPreferredSizeCallBack = ffi.Pointer<
+    ffi.NativeFunction<
+        CFIndex Function(CFIndex, CFOptionFlags, ffi.Pointer<ffi.Void>)>>;
+
+class _ObjCWrapper {
+  final ffi.Pointer<ObjCObject> _id;
+  final NullableTestObjCLibrary _lib;
+  _ObjCWrapper._(this._id, this._lib);
+}
+
+class NullableInterface extends NSObject {
+  NullableInterface._(ffi.Pointer<ObjCObject> id, NullableTestObjCLibrary lib)
+      : super._(id, lib);
+
+  static NullableInterface castFrom<T extends _ObjCWrapper>(T other) {
+    return NullableInterface._(other._id, other._lib);
+  }
+
+  static bool isNullWithNullableNSObjectArg(
+      NullableTestObjCLibrary _lib, NSObject? x) {
+    return _lib._objc_msgSend_4(_lib._class_NullableInterface1,
+        _lib._sel_isNullWithNullableNSObjectArg_1, x?._id ?? ffi.nullptr);
+  }
+
+  static bool isNullWithNotNullableNSObjectPtrArg(
+      NullableTestObjCLibrary _lib, NSObject? x) {
+    return _lib._objc_msgSend_4(_lib._class_NullableInterface1,
+        _lib._sel_isNullWithNotNullableNSObjectPtrArg_1, x?._id ?? ffi.nullptr);
+  }
+
+  static NullableInterface new1(NullableTestObjCLibrary _lib) {
+    final _ret =
+        _lib._objc_msgSend_1(_lib._class_NullableInterface1, _lib._sel_new1);
+    return NullableInterface._(_ret, _lib);
+  }
+
+  static NullableInterface alloc(NullableTestObjCLibrary _lib) {
+    final _ret =
+        _lib._objc_msgSend_1(_lib._class_NullableInterface1, _lib._sel_alloc1);
+    return NullableInterface._(_ret, _lib);
+  }
+}
+
+class ObjCSel extends ffi.Opaque {}
+
+class ObjCObject extends ffi.Opaque {}
+
+class NSObject extends _ObjCWrapper {
+  NSObject._(ffi.Pointer<ObjCObject> id, NullableTestObjCLibrary lib)
+      : super._(id, lib);
+
+  static NSObject castFrom<T extends _ObjCWrapper>(T other) {
+    return NSObject._(other._id, other._lib);
+  }
+
+  static void load(NullableTestObjCLibrary _lib) {
+    _lib._objc_msgSend_0(_lib._class_NSObject1, _lib._sel_load1);
+  }
+
+  static void initialize(NullableTestObjCLibrary _lib) {
+    _lib._objc_msgSend_0(_lib._class_NSObject1, _lib._sel_initialize1);
+  }
+
+  NSObject init() {
+    final _ret = _lib._objc_msgSend_1(_id, _lib._sel_init1);
+    return NSObject._(_ret, _lib);
+  }
+
+  static NSObject new1(NullableTestObjCLibrary _lib) {
+    final _ret = _lib._objc_msgSend_1(_lib._class_NSObject1, _lib._sel_new1);
+    return NSObject._(_ret, _lib);
+  }
+
+  static NSObject allocWithZone(
+      NullableTestObjCLibrary _lib, ffi.Pointer<_NSZone> zone) {
+    final _ret = _lib._objc_msgSend_2(
+        _lib._class_NSObject1, _lib._sel_allocWithZone_1, zone);
+    return NSObject._(_ret, _lib);
+  }
+
+  static NSObject alloc(NullableTestObjCLibrary _lib) {
+    final _ret = _lib._objc_msgSend_1(_lib._class_NSObject1, _lib._sel_alloc1);
+    return NSObject._(_ret, _lib);
+  }
+
+  void dealloc() {
+    _lib._objc_msgSend_0(_id, _lib._sel_dealloc1);
+  }
+
+  void finalize() {
+    _lib._objc_msgSend_0(_id, _lib._sel_finalize1);
+  }
+
+  NSObject copy() {
+    final _ret = _lib._objc_msgSend_1(_id, _lib._sel_copy1);
+    return NSObject._(_ret, _lib);
+  }
+
+  NSObject mutableCopy() {
+    final _ret = _lib._objc_msgSend_1(_id, _lib._sel_mutableCopy1);
+    return NSObject._(_ret, _lib);
+  }
+
+  static NSObject copyWithZone(
+      NullableTestObjCLibrary _lib, ffi.Pointer<_NSZone> zone) {
+    final _ret = _lib._objc_msgSend_2(
+        _lib._class_NSObject1, _lib._sel_copyWithZone_1, zone);
+    return NSObject._(_ret, _lib);
+  }
+
+  static NSObject mutableCopyWithZone(
+      NullableTestObjCLibrary _lib, ffi.Pointer<_NSZone> zone) {
+    final _ret = _lib._objc_msgSend_2(
+        _lib._class_NSObject1, _lib._sel_mutableCopyWithZone_1, zone);
+    return NSObject._(_ret, _lib);
+  }
+
+  static bool instancesRespondToSelector(
+      NullableTestObjCLibrary _lib, ffi.Pointer<ObjCSel> aSelector) {
+    return _lib._objc_msgSend_3(_lib._class_NSObject1,
+        _lib._sel_instancesRespondToSelector_1, aSelector);
+  }
+
+  static bool conformsToProtocol(
+      NullableTestObjCLibrary _lib, NSObject? protocol) {
+    return _lib._objc_msgSend_4(_lib._class_NSObject1,
+        _lib._sel_conformsToProtocol_1, protocol?._id ?? ffi.nullptr);
+  }
+
+  IMP methodForSelector(ffi.Pointer<ObjCSel> aSelector) {
+    return _lib._objc_msgSend_5(_id, _lib._sel_methodForSelector_1, aSelector);
+  }
+
+  static IMP instanceMethodForSelector(
+      NullableTestObjCLibrary _lib, ffi.Pointer<ObjCSel> aSelector) {
+    return _lib._objc_msgSend_5(_lib._class_NSObject1,
+        _lib._sel_instanceMethodForSelector_1, aSelector);
+  }
+
+  void doesNotRecognizeSelector(ffi.Pointer<ObjCSel> aSelector) {
+    _lib._objc_msgSend_6(_id, _lib._sel_doesNotRecognizeSelector_1, aSelector);
+  }
+
+  NSObject forwardingTargetForSelector(ffi.Pointer<ObjCSel> aSelector) {
+    final _ret = _lib._objc_msgSend_7(
+        _id, _lib._sel_forwardingTargetForSelector_1, aSelector);
+    return NSObject._(_ret, _lib);
+  }
+
+  void forwardInvocation(NSObject? anInvocation) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_forwardInvocation_1, anInvocation?._id ?? ffi.nullptr);
+  }
+
+  NSMethodSignature methodSignatureForSelector(ffi.Pointer<ObjCSel> aSelector) {
+    final _ret = _lib._objc_msgSend_9(
+        _id, _lib._sel_methodSignatureForSelector_1, aSelector);
+    return NSMethodSignature._(_ret, _lib);
+  }
+
+  static NSMethodSignature instanceMethodSignatureForSelector(
+      NullableTestObjCLibrary _lib, ffi.Pointer<ObjCSel> aSelector) {
+    final _ret = _lib._objc_msgSend_9(_lib._class_NSObject1,
+        _lib._sel_instanceMethodSignatureForSelector_1, aSelector);
+    return NSMethodSignature._(_ret, _lib);
+  }
+
+  bool allowsWeakReference() {
+    return _lib._objc_msgSend_10(_id, _lib._sel_allowsWeakReference1);
+  }
+
+  bool retainWeakReference() {
+    return _lib._objc_msgSend_10(_id, _lib._sel_retainWeakReference1);
+  }
+
+  static bool isSubclassOfClass(NullableTestObjCLibrary _lib, NSObject aClass) {
+    return _lib._objc_msgSend_4(
+        _lib._class_NSObject1, _lib._sel_isSubclassOfClass_1, aClass._id);
+  }
+
+  static bool resolveClassMethod(
+      NullableTestObjCLibrary _lib, ffi.Pointer<ObjCSel> sel) {
+    return _lib._objc_msgSend_3(
+        _lib._class_NSObject1, _lib._sel_resolveClassMethod_1, sel);
+  }
+
+  static bool resolveInstanceMethod(
+      NullableTestObjCLibrary _lib, ffi.Pointer<ObjCSel> sel) {
+    return _lib._objc_msgSend_3(
+        _lib._class_NSObject1, _lib._sel_resolveInstanceMethod_1, sel);
+  }
+
+  static int hash(NullableTestObjCLibrary _lib) {
+    return _lib._objc_msgSend_11(_lib._class_NSObject1, _lib._sel_hash1);
+  }
+
+  static NSObject superclass(NullableTestObjCLibrary _lib) {
+    final _ret =
+        _lib._objc_msgSend_1(_lib._class_NSObject1, _lib._sel_superclass1);
+    return NSObject._(_ret, _lib);
+  }
+
+  static NSObject class1(NullableTestObjCLibrary _lib) {
+    final _ret = _lib._objc_msgSend_1(_lib._class_NSObject1, _lib._sel_class1);
+    return NSObject._(_ret, _lib);
+  }
+
+  static NSString description(NullableTestObjCLibrary _lib) {
+    final _ret =
+        _lib._objc_msgSend_14(_lib._class_NSObject1, _lib._sel_description1);
+    return NSString._(_ret, _lib);
+  }
+
+  static NSString debugDescription(NullableTestObjCLibrary _lib) {
+    final _ret = _lib._objc_msgSend_14(
+        _lib._class_NSObject1, _lib._sel_debugDescription1);
+    return NSString._(_ret, _lib);
+  }
+}
+
+typedef instancetype = ffi.Pointer<ObjCObject>;
+
+class _NSZone extends ffi.Opaque {}
+
+typedef IMP = ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>;
+
+class NSMethodSignature extends _ObjCWrapper {
+  NSMethodSignature._(ffi.Pointer<ObjCObject> id, NullableTestObjCLibrary lib)
+      : super._(id, lib);
+
+  static NSMethodSignature castFrom<T extends _ObjCWrapper>(T other) {
+    return NSMethodSignature._(other._id, other._lib);
+  }
+}
+
+typedef NSUInteger = pkg_ffi.UnsignedLong;
+
+class NSString extends _ObjCWrapper {
+  NSString._(ffi.Pointer<ObjCObject> id, NullableTestObjCLibrary lib)
+      : super._(id, lib);
+
+  static NSString castFrom<T extends _ObjCWrapper>(T other) {
+    return NSString._(other._id, other._lib);
+  }
+
+  factory NSString(NullableTestObjCLibrary _lib, String str) {
+    final cstr = str.toNativeUtf8();
+    final nsstr = stringWithCString_encoding(_lib, cstr.cast(), 4 /* UTF8 */);
+    pkg_ffi.calloc.free(cstr);
+    return nsstr;
+  }
+
+  @override
+  String toString() => UTF8String().cast<pkg_ffi.Utf8>().toDartString();
+
+  static NSString stringWithCString_encoding(NullableTestObjCLibrary _lib,
+      ffi.Pointer<pkg_ffi.Char> cString, int enc) {
+    final _ret = _lib._objc_msgSend_12(_lib._class_NSString1,
+        _lib._sel_stringWithCString_encoding_1, cString, enc);
+    return NSString._(_ret, _lib);
+  }
+
+  ffi.Pointer<pkg_ffi.Char> UTF8String() {
+    return _lib._objc_msgSend_13(_id, _lib._sel_UTF8String1);
+  }
+}
+
+extension StringToNSString on String {
+  NSString toNSString(NullableTestObjCLibrary lib) => NSString(lib, this);
+}
+
+const int NSScannedOption = 1;
+
+const int NSCollectorDisabledOption = 2;
+
+const int NS_BLOCKS_AVAILABLE = 1;
+
+const int __COREFOUNDATION_CFAVAILABILITY__ = 1;
+
+const int __CF_ENUM_FIXED_IS_AVAILABLE = 1;
+
+const double NSFoundationVersionNumber10_0 = 397.4;
+
+const double NSFoundationVersionNumber10_1 = 425.0;
+
+const double NSFoundationVersionNumber10_1_1 = 425.0;
+
+const double NSFoundationVersionNumber10_1_2 = 425.0;
+
+const double NSFoundationVersionNumber10_1_3 = 425.0;
+
+const double NSFoundationVersionNumber10_1_4 = 425.0;
+
+const double NSFoundationVersionNumber10_2 = 462.0;
+
+const double NSFoundationVersionNumber10_2_1 = 462.0;
+
+const double NSFoundationVersionNumber10_2_2 = 462.0;
+
+const double NSFoundationVersionNumber10_2_3 = 462.0;
+
+const double NSFoundationVersionNumber10_2_4 = 462.0;
+
+const double NSFoundationVersionNumber10_2_5 = 462.0;
+
+const double NSFoundationVersionNumber10_2_6 = 462.0;
+
+const double NSFoundationVersionNumber10_2_7 = 462.7;
+
+const double NSFoundationVersionNumber10_2_8 = 462.7;
+
+const double NSFoundationVersionNumber10_3 = 500.0;
+
+const double NSFoundationVersionNumber10_3_1 = 500.0;
+
+const double NSFoundationVersionNumber10_3_2 = 500.3;
+
+const double NSFoundationVersionNumber10_3_3 = 500.54;
+
+const double NSFoundationVersionNumber10_3_4 = 500.56;
+
+const double NSFoundationVersionNumber10_3_5 = 500.56;
+
+const double NSFoundationVersionNumber10_3_6 = 500.56;
+
+const double NSFoundationVersionNumber10_3_7 = 500.56;
+
+const double NSFoundationVersionNumber10_3_8 = 500.56;
+
+const double NSFoundationVersionNumber10_3_9 = 500.58;
+
+const double NSFoundationVersionNumber10_4 = 567.0;
+
+const double NSFoundationVersionNumber10_4_1 = 567.0;
+
+const double NSFoundationVersionNumber10_4_2 = 567.12;
+
+const double NSFoundationVersionNumber10_4_3 = 567.21;
+
+const double NSFoundationVersionNumber10_4_4_Intel = 567.23;
+
+const double NSFoundationVersionNumber10_4_4_PowerPC = 567.21;
+
+const double NSFoundationVersionNumber10_4_5 = 567.25;
+
+const double NSFoundationVersionNumber10_4_6 = 567.26;
+
+const double NSFoundationVersionNumber10_4_7 = 567.27;
+
+const double NSFoundationVersionNumber10_4_8 = 567.28;
+
+const double NSFoundationVersionNumber10_4_9 = 567.29;
+
+const double NSFoundationVersionNumber10_4_10 = 567.29;
+
+const double NSFoundationVersionNumber10_4_11 = 567.36;
+
+const double NSFoundationVersionNumber10_5 = 677.0;
+
+const double NSFoundationVersionNumber10_5_1 = 677.1;
+
+const double NSFoundationVersionNumber10_5_2 = 677.15;
+
+const double NSFoundationVersionNumber10_5_3 = 677.19;
+
+const double NSFoundationVersionNumber10_5_4 = 677.19;
+
+const double NSFoundationVersionNumber10_5_5 = 677.21;
+
+const double NSFoundationVersionNumber10_5_6 = 677.22;
+
+const double NSFoundationVersionNumber10_5_7 = 677.24;
+
+const double NSFoundationVersionNumber10_5_8 = 677.26;
+
+const double NSFoundationVersionNumber10_6 = 751.0;
+
+const double NSFoundationVersionNumber10_6_1 = 751.0;
+
+const double NSFoundationVersionNumber10_6_2 = 751.14;
+
+const double NSFoundationVersionNumber10_6_3 = 751.21;
+
+const double NSFoundationVersionNumber10_6_4 = 751.29;
+
+const double NSFoundationVersionNumber10_6_5 = 751.42;
+
+const double NSFoundationVersionNumber10_6_6 = 751.53;
+
+const double NSFoundationVersionNumber10_6_7 = 751.53;
+
+const double NSFoundationVersionNumber10_6_8 = 751.62;
+
+const double NSFoundationVersionNumber10_7 = 833.1;
+
+const double NSFoundationVersionNumber10_7_1 = 833.1;
+
+const double NSFoundationVersionNumber10_7_2 = 833.2;
+
+const double NSFoundationVersionNumber10_7_3 = 833.24;
+
+const double NSFoundationVersionNumber10_7_4 = 833.25;
+
+const double NSFoundationVersionNumber10_8 = 945.0;
+
+const double NSFoundationVersionNumber10_8_1 = 945.0;
+
+const double NSFoundationVersionNumber10_8_2 = 945.11;
+
+const double NSFoundationVersionNumber10_8_3 = 945.16;
+
+const double NSFoundationVersionNumber10_8_4 = 945.18;
+
+const int NSFoundationVersionNumber10_9 = 1056;
+
+const int NSFoundationVersionNumber10_9_1 = 1056;
+
+const double NSFoundationVersionNumber10_9_2 = 1056.13;
+
+const double NSFoundationVersionNumber10_10 = 1151.16;
+
+const double NSFoundationVersionNumber10_10_1 = 1151.16;
+
+const double NSFoundationVersionNumber10_10_2 = 1152.14;
+
+const double NSFoundationVersionNumber10_10_3 = 1153.2;
+
+const double NSFoundationVersionNumber10_10_4 = 1153.2;
+
+const int NSFoundationVersionNumber10_10_5 = 1154;
+
+const int NSFoundationVersionNumber10_10_Max = 1199;
+
+const int NSFoundationVersionNumber10_11 = 1252;
+
+const double NSFoundationVersionNumber10_11_1 = 1255.1;
+
+const double NSFoundationVersionNumber10_11_2 = 1256.1;
+
+const double NSFoundationVersionNumber10_11_3 = 1256.1;
+
+const int NSFoundationVersionNumber10_11_4 = 1258;
+
+const int NSFoundationVersionNumber10_11_Max = 1299;
+
+const int __COREFOUNDATION_CFBASE__ = 1;
+
+const int TRUE = 1;
+
+const int FALSE = 0;
+
+const double kCFCoreFoundationVersionNumber10_0 = 196.4;
+
+const double kCFCoreFoundationVersionNumber10_0_3 = 196.5;
+
+const double kCFCoreFoundationVersionNumber10_1 = 226.0;
+
+const double kCFCoreFoundationVersionNumber10_1_1 = 226.0;
+
+const double kCFCoreFoundationVersionNumber10_1_2 = 227.2;
+
+const double kCFCoreFoundationVersionNumber10_1_3 = 227.2;
+
+const double kCFCoreFoundationVersionNumber10_1_4 = 227.3;
+
+const double kCFCoreFoundationVersionNumber10_2 = 263.0;
+
+const double kCFCoreFoundationVersionNumber10_2_1 = 263.1;
+
+const double kCFCoreFoundationVersionNumber10_2_2 = 263.1;
+
+const double kCFCoreFoundationVersionNumber10_2_3 = 263.3;
+
+const double kCFCoreFoundationVersionNumber10_2_4 = 263.3;
+
+const double kCFCoreFoundationVersionNumber10_2_5 = 263.5;
+
+const double kCFCoreFoundationVersionNumber10_2_6 = 263.5;
+
+const double kCFCoreFoundationVersionNumber10_2_7 = 263.5;
+
+const double kCFCoreFoundationVersionNumber10_2_8 = 263.5;
+
+const double kCFCoreFoundationVersionNumber10_3 = 299.0;
+
+const double kCFCoreFoundationVersionNumber10_3_1 = 299.0;
+
+const double kCFCoreFoundationVersionNumber10_3_2 = 299.0;
+
+const double kCFCoreFoundationVersionNumber10_3_3 = 299.3;
+
+const double kCFCoreFoundationVersionNumber10_3_4 = 299.31;
+
+const double kCFCoreFoundationVersionNumber10_3_5 = 299.31;
+
+const double kCFCoreFoundationVersionNumber10_3_6 = 299.32;
+
+const double kCFCoreFoundationVersionNumber10_3_7 = 299.33;
+
+const double kCFCoreFoundationVersionNumber10_3_8 = 299.33;
+
+const double kCFCoreFoundationVersionNumber10_3_9 = 299.35;
+
+const double kCFCoreFoundationVersionNumber10_4 = 368.0;
+
+const double kCFCoreFoundationVersionNumber10_4_1 = 368.1;
+
+const double kCFCoreFoundationVersionNumber10_4_2 = 368.11;
+
+const double kCFCoreFoundationVersionNumber10_4_3 = 368.18;
+
+const double kCFCoreFoundationVersionNumber10_4_4_Intel = 368.26;
+
+const double kCFCoreFoundationVersionNumber10_4_4_PowerPC = 368.25;
+
+const double kCFCoreFoundationVersionNumber10_4_5_Intel = 368.26;
+
+const double kCFCoreFoundationVersionNumber10_4_5_PowerPC = 368.25;
+
+const double kCFCoreFoundationVersionNumber10_4_6_Intel = 368.26;
+
+const double kCFCoreFoundationVersionNumber10_4_6_PowerPC = 368.25;
+
+const double kCFCoreFoundationVersionNumber10_4_7 = 368.27;
+
+const double kCFCoreFoundationVersionNumber10_4_8 = 368.27;
+
+const double kCFCoreFoundationVersionNumber10_4_9 = 368.28;
+
+const double kCFCoreFoundationVersionNumber10_4_10 = 368.28;
+
+const double kCFCoreFoundationVersionNumber10_4_11 = 368.31;
+
+const double kCFCoreFoundationVersionNumber10_5 = 476.0;
+
+const double kCFCoreFoundationVersionNumber10_5_1 = 476.0;
+
+const double kCFCoreFoundationVersionNumber10_5_2 = 476.1;
+
+const double kCFCoreFoundationVersionNumber10_5_3 = 476.13;
+
+const double kCFCoreFoundationVersionNumber10_5_4 = 476.14;
+
+const double kCFCoreFoundationVersionNumber10_5_5 = 476.15;
+
+const double kCFCoreFoundationVersionNumber10_5_6 = 476.17;
+
+const double kCFCoreFoundationVersionNumber10_5_7 = 476.18;
+
+const double kCFCoreFoundationVersionNumber10_5_8 = 476.19;
+
+const double kCFCoreFoundationVersionNumber10_6 = 550.0;
+
+const double kCFCoreFoundationVersionNumber10_6_1 = 550.0;
+
+const double kCFCoreFoundationVersionNumber10_6_2 = 550.13;
+
+const double kCFCoreFoundationVersionNumber10_6_3 = 550.19;
+
+const double kCFCoreFoundationVersionNumber10_6_4 = 550.29;
+
+const double kCFCoreFoundationVersionNumber10_6_5 = 550.42;
+
+const double kCFCoreFoundationVersionNumber10_6_6 = 550.42;
+
+const double kCFCoreFoundationVersionNumber10_6_7 = 550.42;
+
+const double kCFCoreFoundationVersionNumber10_6_8 = 550.43;
+
+const double kCFCoreFoundationVersionNumber10_7 = 635.0;
+
+const double kCFCoreFoundationVersionNumber10_7_1 = 635.0;
+
+const double kCFCoreFoundationVersionNumber10_7_2 = 635.15;
+
+const double kCFCoreFoundationVersionNumber10_7_3 = 635.19;
+
+const double kCFCoreFoundationVersionNumber10_7_4 = 635.21;
+
+const double kCFCoreFoundationVersionNumber10_7_5 = 635.21;
+
+const double kCFCoreFoundationVersionNumber10_8 = 744.0;
+
+const double kCFCoreFoundationVersionNumber10_8_1 = 744.0;
+
+const double kCFCoreFoundationVersionNumber10_8_2 = 744.12;
+
+const double kCFCoreFoundationVersionNumber10_8_3 = 744.18;
+
+const double kCFCoreFoundationVersionNumber10_8_4 = 744.19;
+
+const double kCFCoreFoundationVersionNumber10_9 = 855.11;
+
+const double kCFCoreFoundationVersionNumber10_9_1 = 855.11;
+
+const double kCFCoreFoundationVersionNumber10_9_2 = 855.14;
+
+const double kCFCoreFoundationVersionNumber10_10 = 1151.16;
+
+const double kCFCoreFoundationVersionNumber10_10_1 = 1151.16;
+
+const int kCFCoreFoundationVersionNumber10_10_2 = 1152;
+
+const double kCFCoreFoundationVersionNumber10_10_3 = 1153.18;
+
+const double kCFCoreFoundationVersionNumber10_10_4 = 1153.18;
+
+const double kCFCoreFoundationVersionNumber10_10_5 = 1153.18;
+
+const int kCFCoreFoundationVersionNumber10_10_Max = 1199;
+
+const int kCFCoreFoundationVersionNumber10_11 = 1253;
+
+const double kCFCoreFoundationVersionNumber10_11_1 = 1255.1;
+
+const double kCFCoreFoundationVersionNumber10_11_2 = 1256.14;
+
+const double kCFCoreFoundationVersionNumber10_11_3 = 1256.14;
+
+const double kCFCoreFoundationVersionNumber10_11_4 = 1258.1;
+
+const int kCFCoreFoundationVersionNumber10_11_Max = 1299;
+
+const int ISA_PTRAUTH_DISCRIMINATOR = 27361;
diff --git a/pkgs/ffigen/test/native_objc_test/nullable_config.yaml b/pkgs/ffigen/test/native_objc_test/nullable_config.yaml
new file mode 100644
index 0000000..1d59062
--- /dev/null
+++ b/pkgs/ffigen/test/native_objc_test/nullable_config.yaml
@@ -0,0 +1,12 @@
+name: NullableTestObjCLibrary
+description: 'Tests calling Objective-C methods'
+language: objc
+output: 'test/native_objc_test/nullable_bindings.dart'
+functions:
+  exclude:
+    - '.*'
+headers:
+  entry-points:
+    - 'test/native_objc_test/nullable_test.m'
+preamble: |
+  // ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field
diff --git a/pkgs/ffigen/test/native_objc_test/nullable_test.dart b/pkgs/ffigen/test/native_objc_test/nullable_test.dart
new file mode 100644
index 0000000..fe15f8d
--- /dev/null
+++ b/pkgs/ffigen/test/native_objc_test/nullable_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Objective C support is only available on mac.
+@TestOn('mac-os')
+
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:ffigen/ffigen.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+import 'package:yaml/yaml.dart';
+import '../test_utils.dart';
+import 'nullable_bindings.dart';
+
+void main() {
+  late NullableTestObjCLibrary lib;
+  late NSObject obj;
+  group('method calls', () {
+    setUpAll(() {
+      logWarnings();
+      final dylib = File('test/native_objc_test/nullable_test.dylib');
+      verifySetupFile(dylib);
+      lib = NullableTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path));
+      obj = NSObject.new1(lib);
+    });
+
+    test('generate_bindings', () {
+      final config = Config.fromYaml(loadYaml(
+          File(path.join('test', 'native_objc_test', 'nullable_config.yaml'))
+              .readAsStringSync()) as YamlMap);
+      final library = parse(config);
+      final file = File(
+        path.join('test', 'debug_generated', 'nullable_test.dart'),
+      );
+      library.generateFile(file);
+
+      try {
+        final actual = file.readAsStringSync();
+        final expected = File(path.join(config.output)).readAsStringSync();
+        expect(actual, expected);
+        if (file.existsSync()) {
+          file.delete();
+        }
+      } catch (e) {
+        print('Failed test: Debug generated file: ${file.absolute.path}');
+        rethrow;
+      }
+    });
+
+    group('Nullable arguments', () {
+      test('Not null', () {
+        expect(
+            NullableInterface.isNullWithNullableNSObjectArg(lib, obj), false);
+      });
+      test('Null', () {
+        expect(
+            NullableInterface.isNullWithNullableNSObjectArg(lib, null), true);
+      });
+    });
+
+    group('Not-nullable arguments', () {
+      test('Not null', () {
+        expect(NullableInterface.isNullWithNotNullableNSObjectPtrArg(lib, obj),
+            false);
+      });
+    });
+  });
+}
diff --git a/pkgs/ffigen/test/native_objc_test/nullable_test.m b/pkgs/ffigen/test/native_objc_test/nullable_test.m
new file mode 100644
index 0000000..4733493
--- /dev/null
+++ b/pkgs/ffigen/test/native_objc_test/nullable_test.m
@@ -0,0 +1,21 @@
+#import <Foundation/NSObject.h>
+
+@interface NullableInterface  : NSObject {
+}
+
++(BOOL) isNullWithNullableNSObjectArg:(nullable NSObject *)x;
++(BOOL) isNullWithNotNullableNSObjectPtrArg:(NSObject *)x;
+
+@end
+
+@implementation NullableInterface
+
++(BOOL) isNullWithNullableNSObjectArg:(nullable NSObject *)x {
+  return x == NULL;
+}
+
++(BOOL) isNullWithNotNullableNSObjectPtrArg:(NSObject *)x {
+  return x == NULL;
+}
+
+@end
diff --git a/pkgs/ffigen/test/native_objc_test/property_bindings.dart b/pkgs/ffigen/test/native_objc_test/property_bindings.dart
index f836774..353d0c1 100644
--- a/pkgs/ffigen/test/native_objc_test/property_bindings.dart
+++ b/pkgs/ffigen/test/native_objc_test/property_bindings.dart
@@ -795,9 +795,9 @@
   }
 
   static bool conformsToProtocol(
-      PropertyTestObjCLibrary _lib, NSObject protocol) {
-    return _lib._objc_msgSend_4(
-        _lib._class_NSObject1, _lib._sel_conformsToProtocol_1, protocol._id);
+      PropertyTestObjCLibrary _lib, NSObject? protocol) {
+    return _lib._objc_msgSend_4(_lib._class_NSObject1,
+        _lib._sel_conformsToProtocol_1, protocol?._id ?? ffi.nullptr);
   }
 
   IMP methodForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -820,8 +820,9 @@
     return NSObject._(_ret, _lib);
   }
 
-  void forwardInvocation(NSObject anInvocation) {
-    _lib._objc_msgSend_8(_id, _lib._sel_forwardInvocation_1, anInvocation._id);
+  void forwardInvocation(NSObject? anInvocation) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_forwardInvocation_1, anInvocation?._id ?? ffi.nullptr);
   }
 
   NSMethodSignature methodSignatureForSelector(ffi.Pointer<ObjCSel> aSelector) {
diff --git a/pkgs/ffigen/test/native_objc_test/setup.dart b/pkgs/ffigen/test/native_objc_test/setup.dart
index 86368a1..37e5eac 100644
--- a/pkgs/ffigen/test/native_objc_test/setup.dart
+++ b/pkgs/ffigen/test/native_objc_test/setup.dart
@@ -34,6 +34,7 @@
   print('Building Dynamic Library for Objective C Native Tests...');
   await _buildLib('native_objc_test.m', 'native_objc_test.dylib');
   await _buildLib('method_test.m', 'method_test.dylib');
+  await _buildLib('nullable_test.m', 'nullable_test.dylib');
   await _buildLib('property_test.m', 'property_test.dylib');
   await _buildLib('string_test.m', 'string_test.dylib');
 }
diff --git a/pkgs/ffigen/test/native_objc_test/string_bindings.dart b/pkgs/ffigen/test/native_objc_test/string_bindings.dart
index a4220e5..e1f64f2 100644
--- a/pkgs/ffigen/test/native_objc_test/string_bindings.dart
+++ b/pkgs/ffigen/test/native_objc_test/string_bindings.dart
@@ -2653,9 +2653,9 @@
     return NSValue._(_ret, _lib);
   }
 
-  NSValue initWithCoder(NSObject coder) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithCoder_1, coder._id);
+  NSValue initWithCoder(NSObject? coder) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithCoder_1, coder?._id ?? ffi.nullptr);
     return NSValue._(_ret, _lib);
   }
 
@@ -2751,9 +2751,9 @@
   }
 
   static bool conformsToProtocol(
-      StringTestObjCLibrary _lib, NSObject protocol) {
-    return _lib._objc_msgSend_4(
-        _lib._class_NSObject1, _lib._sel_conformsToProtocol_1, protocol._id);
+      StringTestObjCLibrary _lib, NSObject? protocol) {
+    return _lib._objc_msgSend_4(_lib._class_NSObject1,
+        _lib._sel_conformsToProtocol_1, protocol?._id ?? ffi.nullptr);
   }
 
   IMP methodForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -2776,8 +2776,9 @@
     return NSObject._(_ret, _lib);
   }
 
-  void forwardInvocation(NSObject anInvocation) {
-    _lib._objc_msgSend_8(_id, _lib._sel_forwardInvocation_1, anInvocation._id);
+  void forwardInvocation(NSObject? anInvocation) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_forwardInvocation_1, anInvocation?._id ?? ffi.nullptr);
   }
 
   NSMethodSignature methodSignatureForSelector(ffi.Pointer<ObjCSel> aSelector) {
@@ -2895,9 +2896,9 @@
     return NSString._(_ret, _lib);
   }
 
-  NSString initWithCoder(NSObject coder) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithCoder_1, coder._id);
+  NSString initWithCoder(NSObject? coder) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithCoder_1, coder?._id ?? ffi.nullptr);
     return NSString._(_ret, _lib);
   }
 
@@ -2938,9 +2939,9 @@
   }
 
   @override
-  NSNumber initWithCoder(NSObject coder) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithCoder_1, coder._id);
+  NSNumber initWithCoder(NSObject? coder) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithCoder_1, coder?._id ?? ffi.nullptr);
     return NSNumber._(_ret, _lib);
   }
 
@@ -3091,12 +3092,14 @@
     return NSObject._(_ret, _lib);
   }
 
-  int compare(NSObject otherNumber) {
-    return _lib._objc_msgSend_43(_id, _lib._sel_compare_1, otherNumber._id);
+  int compare(NSObject? otherNumber) {
+    return _lib._objc_msgSend_43(
+        _id, _lib._sel_compare_1, otherNumber?._id ?? ffi.nullptr);
   }
 
-  bool isEqualToNumber(NSObject number) {
-    return _lib._objc_msgSend_4(_id, _lib._sel_isEqualToNumber_1, number._id);
+  bool isEqualToNumber(NSObject? number) {
+    return _lib._objc_msgSend_4(
+        _id, _lib._sel_isEqualToNumber_1, number?._id ?? ffi.nullptr);
   }
 
   NSString descriptionWithLocale(NSObject locale) {
@@ -3264,9 +3267,9 @@
     return NSIndexSet._(_ret, _lib);
   }
 
-  NSIndexSet initWithIndexSet(NSObject indexSet) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithIndexSet_1, indexSet._id);
+  NSIndexSet initWithIndexSet(NSObject? indexSet) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithIndexSet_1, indexSet?._id ?? ffi.nullptr);
     return NSIndexSet._(_ret, _lib);
   }
 
@@ -3275,9 +3278,9 @@
     return NSIndexSet._(_ret, _lib);
   }
 
-  bool isEqualToIndexSet(NSObject indexSet) {
+  bool isEqualToIndexSet(NSObject? indexSet) {
     return _lib._objc_msgSend_4(
-        _id, _lib._sel_isEqualToIndexSet_1, indexSet._id);
+        _id, _lib._sel_isEqualToIndexSet_1, indexSet?._id ?? ffi.nullptr);
   }
 
   int get count {
@@ -3333,8 +3336,9 @@
         _id, _lib._sel_containsIndexesInRange_1, range);
   }
 
-  bool containsIndexes(NSObject indexSet) {
-    return _lib._objc_msgSend_4(_id, _lib._sel_containsIndexes_1, indexSet._id);
+  bool containsIndexes(NSObject? indexSet) {
+    return _lib._objc_msgSend_4(
+        _id, _lib._sel_containsIndexes_1, indexSet?._id ?? ffi.nullptr);
   }
 
   bool intersectsIndexesInRange(NSRange range) {
@@ -3447,12 +3451,14 @@
     return NSMutableIndexSet._(other._id, other._lib);
   }
 
-  void addIndexes(NSObject indexSet) {
-    _lib._objc_msgSend_8(_id, _lib._sel_addIndexes_1, indexSet._id);
+  void addIndexes(NSObject? indexSet) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_addIndexes_1, indexSet?._id ?? ffi.nullptr);
   }
 
-  void removeIndexes(NSObject indexSet) {
-    _lib._objc_msgSend_8(_id, _lib._sel_removeIndexes_1, indexSet._id);
+  void removeIndexes(NSObject? indexSet) {
+    _lib._objc_msgSend_8(
+        _id, _lib._sel_removeIndexes_1, indexSet?._id ?? ffi.nullptr);
   }
 
   void removeAllIndexes() {
@@ -3531,43 +3537,43 @@
     return NSOrderedCollectionDifference._(other._id, other._lib);
   }
 
-  NSOrderedCollectionDifference initWithChanges(NSObject changes) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithChanges_1, changes._id);
+  NSOrderedCollectionDifference initWithChanges(NSObject? changes) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithChanges_1, changes?._id ?? ffi.nullptr);
     return NSOrderedCollectionDifference._(_ret, _lib);
   }
 
   NSOrderedCollectionDifference
       initWithInsertIndexes_insertedObjects_removeIndexes_removedObjects_additionalChanges(
-          NSObject inserts,
-          NSObject insertedObjects,
-          NSObject removes,
-          NSObject removedObjects,
-          NSObject changes) {
+          NSObject? inserts,
+          NSObject? insertedObjects,
+          NSObject? removes,
+          NSObject? removedObjects,
+          NSObject? changes) {
     final _ret = _lib._objc_msgSend_66(
         _id,
         _lib._sel_initWithInsertIndexes_insertedObjects_removeIndexes_removedObjects_additionalChanges_1,
-        inserts._id,
-        insertedObjects._id,
-        removes._id,
-        removedObjects._id,
-        changes._id);
+        inserts?._id ?? ffi.nullptr,
+        insertedObjects?._id ?? ffi.nullptr,
+        removes?._id ?? ffi.nullptr,
+        removedObjects?._id ?? ffi.nullptr,
+        changes?._id ?? ffi.nullptr);
     return NSOrderedCollectionDifference._(_ret, _lib);
   }
 
   NSOrderedCollectionDifference
       initWithInsertIndexes_insertedObjects_removeIndexes_removedObjects(
-          NSObject inserts,
-          NSObject insertedObjects,
-          NSObject removes,
-          NSObject removedObjects) {
+          NSObject? inserts,
+          NSObject? insertedObjects,
+          NSObject? removes,
+          NSObject? removedObjects) {
     final _ret = _lib._objc_msgSend_67(
         _id,
         _lib._sel_initWithInsertIndexes_insertedObjects_removeIndexes_removedObjects_1,
-        inserts._id,
-        insertedObjects._id,
-        removes._id,
-        removedObjects._id);
+        inserts?._id ?? ffi.nullptr,
+        insertedObjects?._id ?? ffi.nullptr,
+        removes?._id ?? ffi.nullptr,
+        removedObjects?._id ?? ffi.nullptr);
     return NSOrderedCollectionDifference._(_ret, _lib);
   }
 
@@ -3633,9 +3639,9 @@
     return NSArray._(_ret, _lib);
   }
 
-  NSArray initWithCoder(NSObject coder) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithCoder_1, coder._id);
+  NSArray initWithCoder(NSObject? coder) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithCoder_1, coder?._id ?? ffi.nullptr);
     return NSArray._(_ret, _lib);
   }
 
@@ -3699,9 +3705,9 @@
   }
 
   @override
-  NSMutableArray initWithCoder(NSObject coder) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithCoder_1, coder._id);
+  NSMutableArray initWithCoder(NSObject? coder) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithCoder_1, coder?._id ?? ffi.nullptr);
     return NSMutableArray._(_ret, _lib);
   }
 
@@ -3744,25 +3750,25 @@
   }
 
   void registerDataRepresentationForTypeIdentifier_visibility_loadHandler(
-      NSObject typeIdentifier, int visibility, NSObject loadHandler) {
+      NSObject? typeIdentifier, int visibility, NSObject loadHandler) {
     _lib._objc_msgSend_71(
         _id,
         _lib._sel_registerDataRepresentationForTypeIdentifier_visibility_loadHandler_1,
-        typeIdentifier._id,
+        typeIdentifier?._id ?? ffi.nullptr,
         visibility,
         loadHandler._id);
   }
 
   void
       registerFileRepresentationForTypeIdentifier_fileOptions_visibility_loadHandler(
-          NSObject typeIdentifier,
+          NSObject? typeIdentifier,
           int fileOptions,
           int visibility,
           NSObject loadHandler) {
     _lib._objc_msgSend_72(
         _id,
         _lib._sel_registerFileRepresentationForTypeIdentifier_fileOptions_visibility_loadHandler_1,
-        typeIdentifier._id,
+        typeIdentifier?._id ?? ffi.nullptr,
         fileOptions,
         visibility,
         loadHandler._id);
@@ -3774,46 +3780,48 @@
     return NSObject._(_ret, _lib);
   }
 
-  bool hasItemConformingToTypeIdentifier(NSObject typeIdentifier) {
+  bool hasItemConformingToTypeIdentifier(NSObject? typeIdentifier) {
     return _lib._objc_msgSend_4(
-        _id, _lib._sel_hasItemConformingToTypeIdentifier_1, typeIdentifier._id);
+        _id,
+        _lib._sel_hasItemConformingToTypeIdentifier_1,
+        typeIdentifier?._id ?? ffi.nullptr);
   }
 
   bool hasRepresentationConformingToTypeIdentifier_fileOptions(
-      NSObject typeIdentifier, int fileOptions) {
+      NSObject? typeIdentifier, int fileOptions) {
     return _lib._objc_msgSend_73(
         _id,
         _lib._sel_hasRepresentationConformingToTypeIdentifier_fileOptions_1,
-        typeIdentifier._id,
+        typeIdentifier?._id ?? ffi.nullptr,
         fileOptions);
   }
 
   NSProgress loadDataRepresentationForTypeIdentifier_completionHandler(
-      NSObject typeIdentifier, NSObject completionHandler) {
+      NSObject? typeIdentifier, NSObject completionHandler) {
     final _ret = _lib._objc_msgSend_74(
         _id,
         _lib._sel_loadDataRepresentationForTypeIdentifier_completionHandler_1,
-        typeIdentifier._id,
+        typeIdentifier?._id ?? ffi.nullptr,
         completionHandler._id);
     return NSProgress._(_ret, _lib);
   }
 
   NSProgress loadFileRepresentationForTypeIdentifier_completionHandler(
-      NSObject typeIdentifier, NSObject completionHandler) {
+      NSObject? typeIdentifier, NSObject completionHandler) {
     final _ret = _lib._objc_msgSend_74(
         _id,
         _lib._sel_loadFileRepresentationForTypeIdentifier_completionHandler_1,
-        typeIdentifier._id,
+        typeIdentifier?._id ?? ffi.nullptr,
         completionHandler._id);
     return NSProgress._(_ret, _lib);
   }
 
   NSProgress loadInPlaceFileRepresentationForTypeIdentifier_completionHandler(
-      NSObject typeIdentifier, NSObject completionHandler) {
+      NSObject? typeIdentifier, NSObject completionHandler) {
     final _ret = _lib._objc_msgSend_74(
         _id,
         _lib._sel_loadInPlaceFileRepresentationForTypeIdentifier_completionHandler_1,
-        typeIdentifier._id,
+        typeIdentifier?._id ?? ffi.nullptr,
         completionHandler._id);
     return NSProgress._(_ret, _lib);
   }
@@ -3827,73 +3835,76 @@
     _lib._objc_msgSend_8(_id, _lib._sel_setSuggestedName_1, value._id);
   }
 
-  NSItemProvider initWithObject(NSObject object) {
-    final _ret =
-        _lib._objc_msgSend_13(_id, _lib._sel_initWithObject_1, object._id);
+  NSItemProvider initWithObject(NSObject? object) {
+    final _ret = _lib._objc_msgSend_13(
+        _id, _lib._sel_initWithObject_1, object?._id ?? ffi.nullptr);
     return NSItemProvider._(_ret, _lib);
   }
 
-  void registerObject_visibility(NSObject object, int visibility) {
-    _lib._objc_msgSend_75(
-        _id, _lib._sel_registerObject_visibility_1, object._id, visibility);
+  void registerObject_visibility(NSObject? object, int visibility) {
+    _lib._objc_msgSend_75(_id, _lib._sel_registerObject_visibility_1,
+        object?._id ?? ffi.nullptr, visibility);
   }
 
   void registerObjectOfClass_visibility_loadHandler(
-      NSObject aClass, int visibility, NSObject loadHandler) {
+      NSObject? aClass, int visibility, NSObject loadHandler) {
     _lib._objc_msgSend_71(
         _id,
         _lib._sel_registerObjectOfClass_visibility_loadHandler_1,
-        aClass._id,
+        aClass?._id ?? ffi.nullptr,
         visibility,
         loadHandler._id);
   }
 
-  bool canLoadObjectOfClass(NSObject aClass) {
+  bool canLoadObjectOfClass(NSObject? aClass) {
     return _lib._objc_msgSend_4(
-        _id, _lib._sel_canLoadObjectOfClass_1, aClass._id);
+        _id, _lib._sel_canLoadObjectOfClass_1, aClass?._id ?? ffi.nullptr);
   }
 
   NSProgress loadObjectOfClass_completionHandler(
-      NSObject aClass, NSObject completionHandler) {
+      NSObject? aClass, NSObject completionHandler) {
     final _ret = _lib._objc_msgSend_74(
         _id,
         _lib._sel_loadObjectOfClass_completionHandler_1,
-        aClass._id,
+        aClass?._id ?? ffi.nullptr,
         completionHandler._id);
     return NSProgress._(_ret, _lib);
   }
 
   NSItemProvider initWithItem_typeIdentifier(
-      NSObject item, NSObject typeIdentifier) {
-    final _ret = _lib._objc_msgSend_76(_id,
-        _lib._sel_initWithItem_typeIdentifier_1, item._id, typeIdentifier._id);
+      NSObject? item, NSObject? typeIdentifier) {
+    final _ret = _lib._objc_msgSend_76(
+        _id,
+        _lib._sel_initWithItem_typeIdentifier_1,
+        item?._id ?? ffi.nullptr,
+        typeIdentifier?._id ?? ffi.nullptr);
     return NSItemProvider._(_ret, _lib);
   }
 
-  NSItemProvider initWithContentsOfURL(NSObject fileURL) {
+  NSItemProvider initWithContentsOfURL(NSObject? fileURL) {
     final _ret = _lib._objc_msgSend_13(
-        _id, _lib._sel_initWithContentsOfURL_1, fileURL._id);
+        _id, _lib._sel_initWithContentsOfURL_1, fileURL?._id ?? ffi.nullptr);
     return NSItemProvider._(_ret, _lib);
   }
 
   void registerItemForTypeIdentifier_loadHandler(
-      NSObject typeIdentifier, NSItemProviderLoadHandler loadHandler) {
+      NSObject? typeIdentifier, NSItemProviderLoadHandler loadHandler) {
     _lib._objc_msgSend_77(
         _id,
         _lib._sel_registerItemForTypeIdentifier_loadHandler_1,
-        typeIdentifier._id,
+        typeIdentifier?._id ?? ffi.nullptr,
         loadHandler);
   }
 
   void loadItemForTypeIdentifier_options_completionHandler(
-      NSObject typeIdentifier,
-      NSObject options,
+      NSObject? typeIdentifier,
+      NSObject? options,
       NSItemProviderCompletionHandler completionHandler) {
     _lib._objc_msgSend_78(
         _id,
         _lib._sel_loadItemForTypeIdentifier_options_completionHandler_1,
-        typeIdentifier._id,
-        options._id,
+        typeIdentifier?._id ?? ffi.nullptr,
+        options?._id ?? ffi.nullptr,
         completionHandler);
   }
 
@@ -3970,9 +3981,9 @@
     return NSMutableString._(other._id, other._lib);
   }
 
-  void replaceCharactersInRange_withString(NSRange range, NSObject aString) {
+  void replaceCharactersInRange_withString(NSRange range, NSObject? aString) {
     _lib._objc_msgSend_79(_id, _lib._sel_replaceCharactersInRange_withString_1,
-        range, aString._id);
+        range, aString?._id ?? ffi.nullptr);
   }
 
   static NSString stringWithCString_encoding(
@@ -4062,9 +4073,12 @@
   }
 
   static NSString strConcat_with(
-      StringTestObjCLibrary _lib, NSObject a, NSObject b) {
+      StringTestObjCLibrary _lib, NSObject? a, NSObject? b) {
     final _ret = _lib._objc_msgSend_80(
-        _lib._class_StringUtil1, _lib._sel_strConcat_with_1, a._id, b._id);
+        _lib._class_StringUtil1,
+        _lib._sel_strConcat_with_1,
+        a?._id ?? ffi.nullptr,
+        b?._id ?? ffi.nullptr);
     return NSString._(_ret, _lib);
   }
 
diff --git a/pkgs/ffigen/test/regen.dart b/pkgs/ffigen/test/regen.dart
index 7d78b6d..675d414 100644
--- a/pkgs/ffigen/test/regen.dart
+++ b/pkgs/ffigen/test/regen.dart
@@ -80,6 +80,11 @@
   );
 
   await _regenConfig(
+    File('test/native_objc_test/nullable_config.yaml'),
+    File('test/native_objc_test/nullable_bindings.dart'),
+  );
+
+  await _regenConfig(
     File('test/native_objc_test/property_config.yaml'),
     File('test/native_objc_test/property_bindings.dart'),
   );
diff --git a/pkgs/ffigen/tool/libclang_config.yaml b/pkgs/ffigen/tool/libclang_config.yaml
index 2c398ed..ccc6b46 100644
--- a/pkgs/ffigen/tool/libclang_config.yaml
+++ b/pkgs/ffigen/tool/libclang_config.yaml
@@ -40,6 +40,7 @@
     - CXTranslationUnit_Flags
     - CXEvalResultKind
     - CXObjCPropertyAttrKind
+    - CXTypeNullabilityKind
 
 structs:
   include:
@@ -114,3 +115,4 @@
     - clang_Cursor_getObjCPropertyAttributes
     - clang_Cursor_getObjCPropertyGetterName
     - clang_Cursor_getObjCPropertySetterName
+    - clang_Type_getNullability