[ffigen] Pointer.fromFunction leaks, so store result in static variable (#459)

diff --git a/pkgs/ffigen/lib/src/code_generator/objc_block.dart b/pkgs/ffigen/lib/src/code_generator/objc_block.dart
index 73f5a31..310fef1 100644
--- a/pkgs/ffigen/lib/src/code_generator/objc_block.dart
+++ b/pkgs/ffigen/lib/src/code_generator/objc_block.dart
@@ -109,16 +109,18 @@
   /// Creates a block from a C function pointer.
   $name.fromFunctionPointer(${w.className} lib, $natFnPtr ptr) :
       this._(lib.${builtInFunctions.newBlock.name}(
-          ${w.ffiLibraryPrefix}.Pointer.fromFunction<
+          _cFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction<
               ${trampFuncType.getCType(w)}>($funcPtrTrampoline
                   $exceptionalReturn).cast(), ptr.cast()), lib);
+  static $voidPtr? _cFuncTrampoline;
 
   /// Creates a block from a Dart function.
   $name.fromFunction(${w.className} lib, ${funcType.getDartType(w)} fn) :
       this._(lib.${builtInFunctions.newBlock.name}(
-          ${w.ffiLibraryPrefix}.Pointer.fromFunction<
+          _dartFuncTrampoline ??= ${w.ffiLibraryPrefix}.Pointer.fromFunction<
               ${trampFuncType.getCType(w)}>($closureTrampoline
                   $exceptionalReturn).cast(), $registerClosure(fn)), lib);
+  static $voidPtr? _dartFuncTrampoline;
 ''');
 
     // Call method.
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart
index 49e2418..9e284b2 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart
@@ -16,6 +16,12 @@
 
 final _logger = Logger('ffigen.header_parser.compounddecl_parser');
 
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _compoundMembersVisitorPtr;
+
 /// Holds temporary information regarding [compound] while parsing.
 class _ParsedCompound {
   Compound compound;
@@ -179,7 +185,8 @@
   _stack.push(parsed);
   final resultCode = clang.clang_visitChildren(
     cursor,
-    Pointer.fromFunction(_compoundMembersVisitor, exceptional_visitor_return),
+    _compoundMembersVisitorPtr ??= Pointer.fromFunction(
+        _compoundMembersVisitor, exceptional_visitor_return),
     nullptr,
   );
   _stack.pop();
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
index 7eb65a8..1353f2d 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
@@ -15,6 +15,12 @@
 
 final _logger = Logger('ffigen.header_parser.enumdecl_parser');
 
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _enumCursorVisitorPtr;
+
 /// Holds temporary information regarding [EnumClass] while parsing.
 class _ParsedEnum {
   EnumClass? enumClass;
@@ -70,7 +76,8 @@
 void _addEnumConstant(clang_types.CXCursor cursor) {
   final resultCode = clang.clang_visitChildren(
     cursor,
-    Pointer.fromFunction(_enumCursorVisitor, exceptional_visitor_return),
+    _enumCursorVisitorPtr ??=
+        Pointer.fromFunction(_enumCursorVisitor, exceptional_visitor_return),
     nullptr,
   );
 
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart
index 753a4b5..cb5fbdb 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart
@@ -19,6 +19,12 @@
 
 final _logger = Logger('ffigen.header_parser.macro_parser');
 
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _macroVariablevisitorPtr;
+
 /// Adds a macro definition to be parsed later.
 void saveMacroDefinition(clang_types.CXCursor cursor) {
   final macroUsr = cursor.usr();
@@ -79,7 +85,8 @@
 
     final resultCode = clang.clang_visitChildren(
       rootCursor,
-      Pointer.fromFunction(_macroVariablevisitor, exceptional_visitor_return),
+      _macroVariablevisitorPtr ??= Pointer.fromFunction(
+          _macroVariablevisitor, exceptional_visitor_return),
       nullptr,
     );
 
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 bace1c4..16cec51 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
@@ -14,6 +14,27 @@
 
 final _logger = Logger('ffigen.header_parser.objcinterfacedecl_parser');
 
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _parseInterfaceVisitorPtr;
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _isClassDeclarationVisitorPtr;
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _parseMethodVisitorPtr;
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _findCategoryInterfaceVisitorPtr;
+
 class _ParsedObjCInterface {
   ObjCInterface interface;
   _ParsedObjCInterface(this.interface);
@@ -75,7 +96,8 @@
   _interfaceStack.push(_ParsedObjCInterface(itf));
   clang.clang_visitChildren(
       cursor,
-      Pointer.fromFunction(_parseInterfaceVisitor, exceptional_visitor_return),
+      _parseInterfaceVisitorPtr ??= Pointer.fromFunction(
+          _parseInterfaceVisitor, exceptional_visitor_return),
       nullptr);
   _interfaceStack.pop();
 
@@ -89,7 +111,7 @@
   _isClassDeclarationResult = true;
   clang.clang_visitChildren(
       cursor,
-      Pointer.fromFunction(
+      _isClassDeclarationVisitorPtr ??= Pointer.fromFunction(
           _isClassDeclarationVisitor, exceptional_visitor_return),
       nullptr);
   return _isClassDeclarationResult;
@@ -218,7 +240,8 @@
   _methodStack.push(parsed);
   clang.clang_visitChildren(
       cursor,
-      Pointer.fromFunction(_parseMethodVisitor, exceptional_visitor_return),
+      _parseMethodVisitorPtr ??=
+          Pointer.fromFunction(_parseMethodVisitor, exceptional_visitor_return),
       nullptr);
   _methodStack.pop();
   if (parsed.hasError) {
@@ -292,7 +315,7 @@
   _findCategoryInterfaceVisitorResult = null;
   clang.clang_visitChildren(
       cursor,
-      Pointer.fromFunction(
+      _findCategoryInterfaceVisitorPtr ??= Pointer.fromFunction(
           _findCategoryInterfaceVisitor, exceptional_visitor_return),
       nullptr);
   final itfCursor = _findCategoryInterfaceVisitorResult;
@@ -312,7 +335,8 @@
   _interfaceStack.push(_ParsedObjCInterface(itf));
   clang.clang_visitChildren(
       cursor,
-      Pointer.fromFunction(_parseInterfaceVisitor, exceptional_visitor_return),
+      _parseInterfaceVisitorPtr ??= Pointer.fromFunction(
+          _parseInterfaceVisitor, exceptional_visitor_return),
       nullptr);
   _interfaceStack.pop();
 
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
index 81c0a77..879dfea 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
@@ -14,11 +14,18 @@
 
 final _logger = Logger('ffigen.header_parser.unnamed_enumdecl_parser');
 
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _unnamedenumCursorVisitorPtr;
+
 /// Saves unnamed enums.
 void saveUnNamedEnum(clang_types.CXCursor cursor) {
   final resultCode = clang.clang_visitChildren(
     cursor,
-    Pointer.fromFunction(_unnamedenumCursorVisitor, exceptional_visitor_return),
+    _unnamedenumCursorVisitorPtr ??= Pointer.fromFunction(
+        _unnamedenumCursorVisitor, exceptional_visitor_return),
     nullptr,
   );
 
diff --git a/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart b/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart
index 7831ae8..b34b1b1 100644
--- a/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart
@@ -21,12 +21,19 @@
 
 late Set<Binding> _bindings;
 
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _rootCursorVisitorPtr;
+
 /// Parses the translation unit and returns the generated bindings.
 Set<Binding> parseTranslationUnit(clang_types.CXCursor translationUnitCursor) {
   _bindings = {};
   final resultCode = clang.clang_visitChildren(
     translationUnitCursor,
-    Pointer.fromFunction(_rootCursorVisitor, exceptional_visitor_return),
+    _rootCursorVisitorPtr ??=
+        Pointer.fromFunction(_rootCursorVisitor, exceptional_visitor_return),
     nullptr,
   );
 
diff --git a/pkgs/ffigen/lib/src/header_parser/utils.dart b/pkgs/ffigen/lib/src/header_parser/utils.dart
index 7352642..5f9bd33 100644
--- a/pkgs/ffigen/lib/src/header_parser/utils.dart
+++ b/pkgs/ffigen/lib/src/header_parser/utils.dart
@@ -127,6 +127,11 @@
   }
 }
 
+Pointer<
+        NativeFunction<
+            Int32 Function(
+                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
+    _printAstVisitorPtr;
 int _printAstVisitorMaxDepth = 0;
 int _printAstVisitor(clang_types.CXCursor cursor, clang_types.CXCursor parent,
     Pointer<Void> clientData) {
@@ -137,7 +142,8 @@
   print(('  ' * depth) + cursor.completeStringRepr());
   clang.clang_visitChildren(
       cursor,
-      Pointer.fromFunction(_printAstVisitor, exceptional_visitor_return),
+      _printAstVisitorPtr ??=
+          Pointer.fromFunction(_printAstVisitor, exceptional_visitor_return),
       Pointer<Void>.fromAddress(depth + 1));
   return clang_types.CXChildVisitResult.CXChildVisit_Continue;
 }