You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用单个循环动态打印ctypes结构体及嵌套结构体的所有字段与值?

用单个循环(递归)遍历ctypes嵌套结构体与数组

问题描述

我用Python的ctypes定义了包含嵌套结构体与数组的多层结构体,目前需要通过多个for循环才能打印所有字段及其对应值。能否仅用一个循环实现该功能,以更高效地完成CSV文件的读写操作?

原代码

import ctypes as c

class list(c.Structure):
    _fields_ = [('x', c.c_uint16),
                ('y', c.c_uint16 * 2)]

class data(c.Structure):
    _fields_ = [('a', c.c_float),
                ('b', c.c_float),
                ('c', c.c_float)]

class parameters(c.Structure):
    _fields_ = [('variable1', c.c_uint16),
                ('variable2', c.c_uint16),
                ('tablelist', list),
                ('datalist', data * 2)]

a = b'\x05\x00\x14\x00\x1E\x00\x0A\x00\x0F\x00\x14\x00\x00\x40\xFA\x43\x66\x26\x16\x44\x33\x33\x48\x44\x66\x26\x96\x43\x33\x33\xC8\x43\x00\x20\xFA\x43'

instance = parameters.from_buffer_copy(a)

原多循环打印输出

<__main__.parameters object at 0x00000267B1615DC0>
---------------------------
variable1 5
variable2 20
tablelist <__main__.list object at 0x00000267B17848C0>       
datalist <__main__.data_Array_2 object at 0x00000267B17848C0>
---------------------------
x 30
y <__main__.c_ushort_Array_2 object at 0x00000267B1784DC0>   
---------------------------
y 10
y 15
---------------------------
<__main__.data object at 0x00000267B1784DC0>
a 500.5
b 600.5999755859375
c 800.7999877929688
<__main__.data object at 0x00000267B1784E40>
a 300.29998779296875
b 400.3999938964844
c 500.25

解决方案:递归遍历函数

可以编写一个递归函数统一处理所有嵌套层级的结构体和数组,无需手动编写多层循环。该函数会遍历所有字段,生成带层级路径的字段名(如tablelist.x、datalist[0].a)与对应值,方便直接用于CSV读写。

实现代码

import ctypes as c
import csv

class list(c.Structure):
    _fields_ = [('x', c.c_uint16),
                ('y', c.c_uint16 * 2)]

class data(c.Structure):
    _fields_ = [('a', c.c_float),
                ('b', c.c_float),
                ('c', c.c_float)]

class parameters(c.Structure):
    _fields_ = [('variable1', c.c_uint16),
                ('variable2', c.c_uint16),
                ('tablelist', list),
                ('datalist', data * 2)]

def traverse_struct(obj, parent_path="", result=None):
    if result is None:
        result = []
    
    # 处理ctypes结构体
    if isinstance(obj, c.Structure):
        for field_name, _ in obj._fields_:
            current_path = f"{parent_path}.{field_name}" if parent_path else field_name
            traverse_struct(getattr(obj, field_name), current_path, result)
    # 处理ctypes数组
    elif hasattr(obj, '_length_') and hasattr(obj, '__getitem__'):
        for idx, element in enumerate(obj):
            current_path = f"{parent_path}[{idx}]"
            traverse_struct(element, current_path, result)
    # 处理基础数据类型
    else:
        result.append((parent_path, obj))
    
    return result

# 测试遍历并打印
a = b'\x05\x00\x14\x00\x1E\x00\x0A\x00\x0F\x00\x14\x00\x00\x40\xFA\x43\x66\x26\x16\x44\x33\x33\x48\x44\x66\x26\x96\x43\x33\x33\xC8\x43\x00\x20\xFA\x43'
instance = parameters.from_buffer_copy(a)
all_fields = traverse_struct(instance)

for path, value in all_fields:
    print(path, value)

# 写入CSV文件
with open('struct_data.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(['字段路径', '值'])
    writer.writerows(all_fields)

运行输出

variable1 5
variable2 20
tablelist.x 30
tablelist.y[0] 10
tablelist.y[1] 15
datalist[0].a 500.5
datalist[0].b 600.5999755859375
datalist[0].c 800.7999877929688
datalist[1].a 300.29998779296875
datalist[1].b 400.3999938964844
datalist[1].c 500.25

说明

  1. 递归逻辑:函数自动识别结构体、数组和基础类型,递归遍历所有层级,无需手动编写多层循环。
  2. 字段路径:生成的路径清晰展示值的层级位置,CSV读取后可直接识别数据归属。
  3. CSV适配:收集到的(路径, 值)列表可直接通过csv.writer写入文件,读写流程高效统一。

内容的提问来源于stack exchange,提问作者Isaac Zaiek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:28:09