Skip to content
This repository was archived by the owner on Oct 30, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions binding/api_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,17 @@ def _public_struct_name(struct: CStruct) -> str:
return "<anonymous>"


def _struct_method_name(function_name: str, struct_c_name: str) -> str:
"""The name the runtimes give a struct method: the part of the function
name after the last ``_`` it shares with the struct's C name, so
lv_grad_linear_init on lv_grad_dsc_t is ``linear_init``
(analyze.noncommon_part; lvgl-bindings#39)."""
n = len(commonprefix([function_name, struct_c_name])) - 1
while n > 0 and function_name[n] != "_":
n -= 1
return function_name[n + 1 :]


def _method_name(function_name: str, receiver: str, module_prefix: str) -> str:
plain = _strip_prefix(function_name, module_prefix)
stems = [receiver]
Expand Down Expand Up @@ -902,12 +913,14 @@ def build_api_model(
for struct in declarations.structs
}
struct_receivers = {}
struct_c_receivers = {}
for struct in declarations.structs:
receiver = struct_names[id(struct)]
for function in index.struct_functions(receiver):
struct_receivers.setdefault(
function.name, struct_python_names[id(struct)]
)
struct_c_receivers.setdefault(function.name, receiver)

constructors = {}
for function in declarations.functions:
Expand Down Expand Up @@ -963,6 +976,10 @@ def build_api_model(
python_name=(
"create"
if role == "constructor"
else _struct_method_name(
function.name, struct_c_receivers[function.name]
)
if role == "struct_method"
else _method_name(function.name, receiver, module_prefix)
if receiver is not None
else plain
Expand Down
11 changes: 11 additions & 0 deletions binding/emit_cpython_glue.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,17 @@ def finish_py_module(max_phase):
name=py_name, san=san
)
)
if registration.struct_names:
# Structs that aren't exported, such as the type of an anonymous
# union field, are still returned by field reads, so their types
# must be ready (lvgl-bindings#39).
for struct_name, generated in generated_structs.items():
if generated and struct_name not in registration.struct_names:
print(
' if (PyType_Ready(&py_{san}_type) < 0) return NULL;'.format(
san=sanitize(struct_name)
)
)

for global_name in cpython_global_types:
global_type = cpython_global_types.get(global_name)
Expand Down
21 changes: 20 additions & 1 deletion binding/emit_cpython_native.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,27 @@ def try_generate_struct_cpython(struct_name, struct):
)

for decl in flatten_struct_decls:
try_generate_type(decl.type)
converted = try_generate_type(decl.type)
type_name = get_type_fn(decl.type, remove_quals=True)
if (
not converted
and ("\n" in type_name or "{" in type_name)
and isinstance(decl.type, c_ast.TypeDecl)
and is_struct(decl.type.type)
):
# An anonymous struct or union member (lv_grad_dsc_t.params):
# name its type and bind it as a struct, as MicroPython does
# (lvgl-bindings#39).
type_name = "%s_%s_t" % (struct_name[:-2], decl.type.declname)
print(
"typedef __typeof__( (({tag}{parent}*)(0))->{child} ) {new};".format(
tag=struct_tag,
parent=struct_name,
child=decl.type.declname,
new=type_name,
)
)
try_generate_struct_cpython(type_name, decl.type.type)
if "\n" in type_name or "{" in type_name:
continue
if not is_struct(decl.type.type):
Expand Down
Loading
Loading