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.
This commit is contained in:
Ole André Vadla Ravnås committed 2026-09-17 19:01:25 +02:00
1 parent 6681be7efb
commit 636edda25f
3 files changed
+38 -6

No files matched your search

+20 -3
View File
@@ -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:
+17 -2
View File
@@ -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,