mirror of
https://github.com/lvgl/lvgl.git
synced 2026-03-23 22:39:09 +08:00
chore(gdb): add LVSubject/LVObserver wrappers with gen_subject_consts and info subject command
This commit is contained in:
@@ -43,6 +43,9 @@ from .lvgl import (
|
||||
INDEV_TYPE_NAMES,
|
||||
LVGroup,
|
||||
LVObjClass,
|
||||
LVSubject,
|
||||
LVObserver,
|
||||
SUBJECT_TYPE_NAMES,
|
||||
)
|
||||
from . import cmds as cmds
|
||||
|
||||
@@ -89,4 +92,7 @@ __all__ = [
|
||||
"INDEV_TYPE_NAMES",
|
||||
"LVGroup",
|
||||
"LVObjClass",
|
||||
"LVSubject",
|
||||
"LVObserver",
|
||||
"SUBJECT_TYPE_NAMES",
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import gdb
|
||||
|
||||
from .core import DumpObj, DumpIndev, DumpGroup, InfoObjClass
|
||||
from .core import DumpObj, DumpIndev, DumpGroup, InfoObjClass, InfoSubject
|
||||
from .display import DumpDisplayBuf
|
||||
from .draw import InfoDrawUnit, DumpDrawTask
|
||||
from .misc import (
|
||||
@@ -46,6 +46,7 @@ DumpDrawTask()
|
||||
InfoStyle()
|
||||
InfoDrawUnit()
|
||||
InfoObjClass()
|
||||
InfoSubject()
|
||||
|
||||
# Drivers
|
||||
Lvglobal()
|
||||
|
||||
@@ -2,10 +2,12 @@ from .lv_obj import DumpObj
|
||||
from .lv_indev import DumpIndev
|
||||
from .lv_group import DumpGroup
|
||||
from .lv_obj_class import InfoObjClass
|
||||
from .lv_observer import InfoSubject
|
||||
|
||||
__all__ = [
|
||||
"DumpObj",
|
||||
"DumpIndev",
|
||||
"DumpGroup",
|
||||
"InfoObjClass",
|
||||
"InfoSubject",
|
||||
]
|
||||
|
||||
23
scripts/gdb/lvglgdb/cmds/core/lv_observer.py
Normal file
23
scripts/gdb/lvglgdb/cmds/core/lv_observer.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import gdb
|
||||
|
||||
from lvglgdb.lvgl.core.lv_observer import LVSubject
|
||||
|
||||
|
||||
class InfoSubject(gdb.Command):
|
||||
"""show subject and its observers"""
|
||||
|
||||
def __init__(self):
|
||||
super(InfoSubject, self).__init__(
|
||||
"info subject", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
if not args.strip():
|
||||
print("Usage: info subject <expression>")
|
||||
return
|
||||
try:
|
||||
subject = LVSubject(args.strip())
|
||||
except gdb.error as e:
|
||||
print(f"Error: {e}")
|
||||
return
|
||||
subject.print_info()
|
||||
@@ -8,6 +8,9 @@ from .core import (
|
||||
INDEV_TYPE_NAMES,
|
||||
LVGroup,
|
||||
LVObjClass,
|
||||
LVSubject,
|
||||
LVObserver,
|
||||
SUBJECT_TYPE_NAMES,
|
||||
)
|
||||
from .display import LVDisplay
|
||||
from .draw import (
|
||||
@@ -100,4 +103,7 @@ __all__ = [
|
||||
"INDEV_TYPE_NAMES",
|
||||
"LVGroup",
|
||||
"LVObjClass",
|
||||
"LVSubject",
|
||||
"LVObserver",
|
||||
"SUBJECT_TYPE_NAMES",
|
||||
]
|
||||
|
||||
@@ -3,6 +3,8 @@ from .lv_global import curr_inst
|
||||
from .lv_indev import LVIndev, INDEV_TYPE_NAMES
|
||||
from .lv_group import LVGroup
|
||||
from .lv_obj_class import LVObjClass
|
||||
from .lv_observer import LVSubject, LVObserver
|
||||
from .lv_observer_consts import SUBJECT_TYPE_NAMES
|
||||
|
||||
__all__ = [
|
||||
"LVObject",
|
||||
@@ -14,4 +16,7 @@ __all__ = [
|
||||
"INDEV_TYPE_NAMES",
|
||||
"LVGroup",
|
||||
"LVObjClass",
|
||||
"LVSubject",
|
||||
"LVObserver",
|
||||
"SUBJECT_TYPE_NAMES",
|
||||
]
|
||||
|
||||
77
scripts/gdb/lvglgdb/lvgl/core/lv_observer.py
Normal file
77
scripts/gdb/lvglgdb/lvgl/core/lv_observer.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from lvglgdb.value import Value, ValueInput
|
||||
from ..misc.lv_ll import LVList
|
||||
from .lv_observer_consts import SUBJECT_TYPE_NAMES
|
||||
|
||||
|
||||
class LVObserver(Value):
|
||||
"""LVGL observer wrapper"""
|
||||
|
||||
def __init__(self, obs: ValueInput):
|
||||
super().__init__(Value.normalize(obs, "lv_observer_t"))
|
||||
|
||||
@property
|
||||
def subject(self) -> Value:
|
||||
return self.super_value("subject")
|
||||
|
||||
@property
|
||||
def cb(self) -> Value:
|
||||
return self.super_value("cb")
|
||||
|
||||
@property
|
||||
def target(self) -> Value:
|
||||
return self.super_value("target")
|
||||
|
||||
@property
|
||||
def user_data(self) -> Value:
|
||||
return self.super_value("user_data")
|
||||
|
||||
@property
|
||||
def auto_free_user_data(self) -> bool:
|
||||
return bool(int(self.super_value("auto_free_user_data")))
|
||||
|
||||
@property
|
||||
def notified(self) -> bool:
|
||||
return bool(int(self.super_value("notified")))
|
||||
|
||||
@property
|
||||
def for_obj(self) -> bool:
|
||||
return bool(int(self.super_value("for_obj")))
|
||||
|
||||
def print_info(self):
|
||||
cb_str = self.cb.format_string(symbols=True, address=True)
|
||||
print(
|
||||
f" Observer: cb={cb_str} target={self.target}" f" for_obj={self.for_obj}"
|
||||
)
|
||||
|
||||
|
||||
class LVSubject(Value):
|
||||
"""LVGL subject wrapper"""
|
||||
|
||||
def __init__(self, subject: ValueInput):
|
||||
super().__init__(Value.normalize(subject, "lv_subject_t"))
|
||||
|
||||
@property
|
||||
def type(self) -> int:
|
||||
return int(self.super_value("type"))
|
||||
|
||||
@property
|
||||
def type_name(self) -> str:
|
||||
return SUBJECT_TYPE_NAMES.get(self.type, f"UNKNOWN({self.type})")
|
||||
|
||||
@property
|
||||
def size(self) -> int:
|
||||
return int(self.super_value("size"))
|
||||
|
||||
@property
|
||||
def user_data(self) -> Value:
|
||||
return self.super_value("user_data")
|
||||
|
||||
def __iter__(self):
|
||||
for obs in LVList(self.subs_ll, "lv_observer_t"):
|
||||
yield LVObserver(obs)
|
||||
|
||||
def print_info(self):
|
||||
ll = LVList(self.subs_ll, "lv_observer_t")
|
||||
print(f"Subject: type={self.type_name} subscribers={ll.len}")
|
||||
for obs in self.__iter__():
|
||||
obs.print_info()
|
||||
17
scripts/gdb/lvglgdb/lvgl/core/lv_observer_consts.py
Normal file
17
scripts/gdb/lvglgdb/lvgl/core/lv_observer_consts.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""
|
||||
Auto-generated observer constants from LVGL headers.
|
||||
|
||||
Do not edit manually. Regenerate with:
|
||||
python3 scripts/gen_subject_consts.py
|
||||
"""
|
||||
|
||||
SUBJECT_TYPE_NAMES = {
|
||||
0: "INVALID",
|
||||
1: "NONE",
|
||||
2: "INT",
|
||||
3: "FLOAT",
|
||||
4: "POINTER",
|
||||
5: "COLOR",
|
||||
6: "GROUP",
|
||||
7: "STRING",
|
||||
}
|
||||
56
scripts/gdb/scripts/gen_subject_consts.py
Normal file
56
scripts/gdb/scripts/gen_subject_consts.py
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate subject type constant table from LVGL header files.
|
||||
|
||||
Parses lv_observer.h for subject type enum.
|
||||
|
||||
Usage:
|
||||
python3 scripts/gen_subject_consts.py
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GDB_ROOT = SCRIPT_DIR.parent
|
||||
LVGL_SRC = GDB_ROOT.parent.parent / "src"
|
||||
OUTPUT = GDB_ROOT / "lvglgdb" / "lvgl" / "core" / "lv_observer_consts.py"
|
||||
|
||||
OBSERVER_H = LVGL_SRC / "core" / "lv_observer.h"
|
||||
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
from gen_indev_consts import parse_enum
|
||||
|
||||
|
||||
def generate(subject_types: dict[int, str]) -> str:
|
||||
"""Generate Python source for the observer constants module."""
|
||||
lines = [
|
||||
'"""',
|
||||
"Auto-generated observer constants from LVGL headers.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate with:",
|
||||
" python3 scripts/gen_subject_consts.py",
|
||||
'"""',
|
||||
"",
|
||||
"SUBJECT_TYPE_NAMES = {",
|
||||
]
|
||||
for k in sorted(subject_types):
|
||||
lines.append(f' {k}: "{subject_types[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
subject_types = parse_enum(
|
||||
OBSERVER_H, "lv_subject_type_t", "LV_SUBJECT_TYPE_"
|
||||
)
|
||||
src = generate(subject_types)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT} ({len(subject_types)} subject types)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user