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

在ctypes中使用指向自定义CNode数组的指针报错,如何修复?

问题描述

定义的ctypes树结构:

from ctypes import Structure, c_int32, POINTER

class CNode(Structure):
    pass

CNode._fields_ = [
    ("type", c_int32),
    ("children", POINTER(CNode)),
]

转换Python树到CNode树的函数:

def gen_c_tree(tree):
    cnode = gen_c_node(tree)

    if len(tree.children) > 0:
        tmp = [gen_c_node(child) for child in tree.children]
        cnode.children = POINTER(CNode * len(tree.children))(*tmp)

    return cnode

运行时触发错误:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "path/file", line 32, in <module>
    genctree.gen_c_tree(parser.tree)
  File "path/file", line 29, in gen_c_tree
    cnode.children = POINTER(CNode * len(tree.children))(*tmp)
    ^^^^^^^^^^^^^^
TypeError: incompatible types, LP_CNode_Array_1 instance instead of LP_CNode instance
修复方案

错误原因

POINTER(CNode * len(tree.children))(*tmp) 创建的是指向CNode数组类型的指针(比如LP_CNode_Array_1),但CNode的children字段定义的是指向单个CNode的指针(LP_CNode),二者类型不兼容。

修改后的代码

from ctypes import cast, POINTER

def gen_c_tree(tree):
    cnode = gen_c_node(tree)

    if len(tree.children) > 0:
        tmp = [gen_c_node(child) for child in tree.children]
        # 创建对应长度的CNode数组类型
        CNodeArrayType = CNode * len(tmp)
        # 用子节点初始化数组
        children_array = CNodeArrayType(*tmp)
        # 将数组转换为指向CNode的指针(对应C语言中数组名转指针的行为)
        cnode.children = cast(children_array, POINTER(CNode))
        # 关键:保存数组的引用,避免Python垃圾回收销毁数组导致野指针
        cnode._children_array = children_array

    return cnode

关键说明

  1. 类型转换:用cast把CNode数组转换成POINTER(CNode),匹配字段定义的类型,这对应C语言里数组隐式转为首元素指针的行为。
  2. 引用保留:必须把children_array绑定到cnode的属性上(比如_children_array),否则Python的垃圾回收会在函数结束后销毁数组,导致C端访问到无效内存。

内容的提问来源于stack exchange,提问作者Amol Borkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 23:02:38