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

在__init_subclass__中用ctypes.POINTER创建结构体子类指针报错排查

问题:ctypes创建指针时触发TypeError: _type_ must have storage info错误

报错代码示例

执行第6行p = ctypes.POINTER(cls)时触发错误:

import ctypes
from ctypes.wintypes import *

class xStructure(ctypes.Structure):
    def __init_subclass__(cls):
        p = ctypes.POINTER(cls)

class OFFSET_VAL_II_C4(xStructure):
    _fields_ = [('ValOrig', DOUBLE),
                ('MaxChangeVal', DOUBLE),
                ('ActChangeVal', DOUBLE)]

正常运行代码示例

import ctypes
from ctypes.wintypes import *

class xStructure(ctypes.Structure):
    pass

class OFFSET_VAL_II_C4(xStructure):
    _fields_ = [('ValOrig', DOUBLE),
                ('MaxChangeVal', DOUBLE),
                ('ActChangeVal', DOUBLE)]

p = ctypes.POINTER(OFFSET_VAL_II_C4)

原因分析

核心问题在于__init_subclass__的执行时机:

  • 当定义OFFSET_VAL_II_C4并继承xStructure时,Python会立即调用父类的__init_subclass__方法,此时cls(即OFFSET_VAL_II_C4)已经被创建,但还未设置_fields_属性。
  • ctypes要求结构体类必须设置_fields_后,才会生成对应的存储信息(用于和C类型交互的底层数据结构),此时尝试创建指针ctypes.POINTER(cls),ctypes会认为这个类不是合法的ctype类型,因此抛出TypeError。
  • 第二个示例中,ctypes.POINTER(OFFSET_VAL_II_C4)是在OFFSET_VAL_II_C4的_fields_完全设置完成后才执行的,此时类已经具备了ctype所需的存储信息,所以能正常运行。

解决方案

如果需要在父类的__init_subclass__中创建子类的指针类型,需要确保子类的_fields_已经被处理完毕。可以通过以下方式实现:

方式1:延迟指针创建逻辑

将指针创建逻辑放到子类实例化或其他后续时机,比如定义一个类方法:

import ctypes
from ctypes.wintypes import *

class xStructure(ctypes.Structure):
    @classmethod
    def get_pointer_type(cls):
        return ctypes.POINTER(cls)

class OFFSET_VAL_II_C4(xStructure):
    _fields_ = [('ValOrig', DOUBLE),
                ('MaxChangeVal', DOUBLE),
                ('ActChangeVal', DOUBLE)]

# 此时调用已没问题
p = OFFSET_VAL_II_C4.get_pointer_type()

方式2:利用元类确保_fields_初始化完成

通过自定义元类,在类完全创建(包括_fields_处理)后再生成指针类型:

import ctypes
from ctypes.wintypes import *

class StructureMeta(ctypes.Structure.__class__):
    def __new__(meta, name, bases, namespace):
        cls = super().__new__(meta, name, bases, namespace)
        # 此时_fields_已经被ctypes处理完毕
        cls.pointer_type = ctypes.POINTER(cls)
        return cls

class xStructure(ctypes.Structure, metaclass=StructureMeta):
    pass

class OFFSET_VAL_II_C4(xStructure):
    _fields_ = [('ValOrig', DOUBLE),
                ('MaxChangeVal', DOUBLE),
                ('ActChangeVal', DOUBLE)]

# 直接使用子类的pointer_type属性
p = OFFSET_VAL_II_C4.pointer_type

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:11:05