From 636edda25faa4c78f49396214e6dbcd77894d047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Thu, 17 Sep 2026 16:35:50 +0200 Subject: [PATCH] bindgen: Fix dropped constructors and out params A static function that makes the class it sits on was not read at all, so every named constructor in the API was missing. An out parameter fared worse: it was declared as the pointer it is passed through, handed to the C function uninitialised and by value, and left out of the result. A `gboolean` method that answers through one now binds as a nullable, and any other out parameter is refused rather than bound as a result the caller cannot read. --- frida-bindgen | 2 +- src/frida_bindgen/codegen.py | 23 ++++++++++++++++++++--- src/frida_bindgen/model.py | 19 +++++++++++++++++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/frida-bindgen b/frida-bindgen index df17879..eace049 160000 --- a/frida-bindgen +++ b/frida-bindgen @@ -1 +1 @@ -Subproject commit df17879d92d2700a7f1228a03271ba07e2fb579b +Subproject commit eace04901ef6300429e8c343095297df042dba0e diff --git a/src/frida_bindgen/codegen.py b/src/frida_bindgen/codegen.py index 1fb7dbc..8ea7e38 100644 --- a/src/frida_bindgen/codegen.py +++ b/src/frida_bindgen/codegen.py @@ -4,6 +4,7 @@ import textwrap from pathlib import Path from typing import Dict, List, Optional +from frida_bindgen_core import Direction from .model import (ClassObjectType, CustomTypeKind, Enumeration, InterfaceObjectType, Method, Model, ObjectType, Parameter, Procedure, Property, Signal, Tuple, to_camel_case, @@ -1517,8 +1518,12 @@ def generate_parameter_variable_declarations( decls = [] for param in proc.parameters: - line = f"{param.type.c.replace('const ', '')} {param.name}" - if initialize: + c_type = param.type.c.replace("const ", "") + is_out = param.direction == Direction.OUT + if is_out: + c_type = c_type[:-1].strip() + line = f"{c_type} {param.name}" + if initialize and not is_out: default_val = param.type.default_value if default_val is not None: line += f" = {default_val}" @@ -1592,7 +1597,12 @@ def generate_call_arguments_code( names = [] if instance_arg is not None: names.append(instance_arg) - names += [f"{storage_prefix}{param.name}" for param in proc.parameters] + names += [ + f"&{storage_prefix}{param.name}" + if param.direction == Direction.OUT + else f"{storage_prefix}{param.name}" + for param in proc.parameters + ] if proc.throws: names.append(f"&{storage_prefix}error") return ", ".join(names) @@ -1611,6 +1621,13 @@ def generate_return_assignment_code(method: Method, storage_prefix: str) -> str: def generate_return_conversion_code(method: Method, storage_prefix: str) -> str: + out = method.optional_out_parameter + if out is not None: + convert = f"js_retval = fdn_{out.type.nick}_to_value (env, {storage_prefix}{out.name});" + return (f"if ({storage_prefix}retval)" + "\n" + + f" {convert}" + "\n" + + "else" + "\n" + + " napi_get_null (env, &js_retval);") if method.return_value is not None: custom = method.customizations if custom is not None and custom.return_cconversion is not None: diff --git a/src/frida_bindgen/model.py b/src/frida_bindgen/model.py index 5e4d6af..65680be 100644 --- a/src/frida_bindgen/model.py +++ b/src/frida_bindgen/model.py @@ -39,6 +39,13 @@ class Model(core.Model): class ObjectType(core.ObjectType): + @cached_property + def methods(self) -> List["Method"]: + return [ + m for m in super().methods + if not m.out_parameters or m.optional_out_parameter is not None + ] + @cached_property def js_name(self) -> str: custom = self.customizations @@ -211,8 +218,12 @@ class Method(core.Method): @cached_property def prefixed_return_typing(self) -> str: - retval = self.return_value - typing = retval.typing if retval is not None else "void" + out = self.optional_out_parameter + if out is not None: + typing = f"{self.object_type.model.resolve_js_type(out.type)} | null" + else: + retval = self.return_value + typing = retval.typing if retval is not None else "void" return f"Promise<{typing}>" if self.is_async else typing @property @@ -559,6 +570,7 @@ def _make_class( type_struct, parent, constructors, + functions, methods, properties, signals, @@ -573,6 +585,7 @@ def _make_class( type_struct, parent, constructors, + functions, methods, properties, signals, @@ -590,6 +603,7 @@ def _make_interface( type_struct, parent, constructors, + functions, methods, properties, signals, @@ -603,6 +617,7 @@ def _make_interface( type_struct, parent, constructors, + functions, methods, properties, signals,