尝试进行 Qt 测试,增加了 AI 人机调试工具 _console,以及 TransPyV 进行修正

This commit is contained in:
2026-07-21 14:41:22 +08:00
parent a277ded8d4
commit 135aa05485
311 changed files with 7084 additions and 2131 deletions

View File

@@ -253,6 +253,10 @@ class ClassHandle(BaseHandle):
return 'union'
if issubclass(cls, t.CStruct):
return 'struct'
# CType 及其子类CChar/CInt/CVoid/CPtr 等)是"类型强转"标记,
# 不应被编译为真实结构体。
if issubclass(cls, t.CType):
return 'ctype_marker'
# 2) 查 t 模块属性(直接引用 t.CEnum 等)
t_cls: type | None = getattr(t, base_name, None)
@@ -263,9 +267,47 @@ class ClassHandle(BaseHandle):
return 'union'
if issubclass(t_cls, t.CStruct):
return 'struct'
# CType 及其子类是"类型强转"标记,不编译为结构体。
return 'ctype_marker'
return None
@staticmethod
def _is_classname_ctype_marker(class_name: str) -> bool:
"""检查类名是否是 t.CType 的"类型强转"标记子类。
只有 position 不含 BASE 的纯修饰符/标记类型CPtr/CVolatile/CConst/
CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等)
才应跳过编译。有 BASE position 的基本类型CInt/CChar/CSizeT/CLong 等)
有具体大小应被正常编译。CType 基类本身无 basesbase 检测无法触发,
需要直接按类名检查。
注意CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault
所以这里直接用 getattr(t, name) 检查 t 模块属性。
Returns:
True 如果 class_name 是 CType 标记子类名(应跳过编译)
"""
if not class_name:
return False
# 直接查 t 模块属性CTypeRegistry._build 会跳过 CType/CTypeDefault/BigEndian/LittleEndian
t_cls: type | None = getattr(t, class_name, None)
if not isinstance(t_cls, type) or not issubclass(t_cls, t.CType):
return False
if issubclass(t_cls, (t.CStruct, t.CEnum, t.REnum, t.CUnion)):
return False
# 基本类型position 含 BASE 且 Size > 0有具体大小不应跳过
# CVoid 虽含 BASE 但 Size=0CType Size=None仍需跳过
if t.CType.BASE in t_cls.position:
try:
inst = t_cls()
size_val = getattr(inst, 'Size', None)
if size_val is not None and size_val > 0:
return False
except Exception:
pass
return True
def _resolve_decorator_kind(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> str | None:
"""从装饰器列表中解析结构体类型种类
@@ -409,6 +451,11 @@ class ClassHandle(BaseHandle):
def _EmitClassLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, declare_only: bool = False) -> None:
ClassName: str = Node.name
# t.CType 及其子类CChar/CInt/CVoid/CPtr/CTypeDefault 等)是"类型强转"标记,
# 不应被编译为真实结构体。CType 基类本身无 basesbase 检测无法触发,
# 此处在方法入口直接按类名跳过。
if self._is_classname_ctype_marker(ClassName):
return
if self._is_generic_class(Node):
if not hasattr(self, '_generic_class_templates'):
self._generic_class_templates = {}
@@ -449,6 +496,10 @@ class ClassHandle(BaseHandle):
IsCunion = True
elif kind == 'renum':
IsRenum = True
elif kind == 'ctype_marker':
# CType 及其子类CChar/CInt/CVoid/CPtr/CTypeDefault 等)是
# "类型强转"标记,不应被编译为真实结构体。直接 return 跳过编译。
return
if IsCenum:
self._RegisterEnumMembers(Node)
return
@@ -540,50 +591,33 @@ class ClassHandle(BaseHandle):
if pm_name in parent_defaults:
Gen.class_member_defaults[ClassName][pm_name] = parent_defaults[pm_name]
Gen.class_members[ClassName] = inherited + Gen.class_members[ClassName]
if ParentClass in Gen.class_methods:
parent_methods: list = list(Gen.class_methods[ParentClass])
# 从 Node.body 收集子类有方法(此时 Gen.class_methods[ClassName] 可能为空,
# 因为自有方法在 L660-676 才注册。若直接用 Gen.class_methods[ClassName]
# child_method_map 会为空,所有父类方法被当作"未覆盖"添加为包装器,
# 然后 register_method 又把它们追加到 Gen.class_methods[ClassName]
# L566 循环再次添加 → 产生重复条目vtable 布局与导入模块不一致)
child_method_map: dict[str, str] = {}
child_self_methods_snapshot: list[str] = []
for _item in Node.body:
if isinstance(_item, ast.FunctionDef):
_mname: str = _item.name
if _mname in ('__new__', '__init__', '__before_init__'):
continue
_item_meta: FuncMeta = self.Trans.FunctionHandler._ExtractFuncMeta(_item.decorator_list)
if FuncMeta.PROPERTY_SETTER in _item_meta:
_full: str = f"{ClassName}.{_mname}$set"
elif FuncMeta.PROPERTY_DELETER in _item_meta:
_full = f"{ClassName}.{_mname}$del"
else:
_full = f"{ClassName}.{_mname}"
_short: str = _mname
child_method_map[_short] = _full
child_self_methods_snapshot.append(_full)
# 父类方法在前(保证 vtable 布局一致性,子类多态分派索引正确),
# 子类新增方法在后。子类覆盖的方法放在父类方法的位置(用子类实现)。
new_methods: list = []
covered_names: set[str] = set()
for pm in parent_methods:
method_name: str = pm.split('.')[-1] if '.' in pm else pm
if method_name in child_method_map:
# 子类覆盖了父类方法 — 用子类的实现,放在父类的位置
new_methods.append(child_method_map[method_name])
covered_names.add(method_name)
else:
# 父类独有方法 — 子类未覆盖,注册子类包装器
child_method: str = f"{ClassName}.{method_name}"
new_methods.append(child_method)
Gen.register_method(ClassName, child_method)
# 添加子类新增方法(不在父类中的)— 使用快照避免 register_method 污染
for m in child_self_methods_snapshot:
method_name: str = m.split('.')[-1] if '.' in m else m
if method_name not in covered_names:
new_methods.append(m)
if ParentClass in Gen.class_methods:
parent_methods: list = list(Gen.class_methods[ParentClass])
# 构建子类有方法映射(方法短名 -> 方法全名)
child_method_map: dict[str, str] = {}
for m in Gen.class_methods[ClassName]:
method_name: str = m.split('.')[-1] if '.' in m else m
child_method_map[method_name] = m
# 父类方法在前(保证 vtable 布局一致性,子类多态分派索引正确),
# 子类新增方法在后。子类覆盖的方法放在父类方法的位置(用子类实现)。
new_methods: list = []
covered_names: set[str] = set()
for pm in parent_methods:
method_name: str = pm.split('.')[-1] if '.' in pm else pm
if method_name in child_method_map:
# 子类覆盖了父类方法 — 用子类的实现,放在父类的位置
new_methods.append(child_method_map[method_name])
covered_names.add(method_name)
else:
# 父类独有方法 — 子类未覆盖,注册子类包装器
child_method: str = f"{ClassName}.{method_name}"
new_methods.append(child_method)
Gen.register_method(ClassName, child_method)
# 添加子类新增方法(不在父类中的)
for m in Gen.class_methods[ClassName]:
method_name: str = m.split('.')[-1] if '.' in m else m
if method_name not in covered_names:
new_methods.append(m)
Gen.class_methods[ClassName] = new_methods
# 提取首个裸字符串字面量作为结构体 __doc__ docstring
if (Node.body and isinstance(Node.body[0], ast.Expr)