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

如何调整ctypes定义的tagSAFEARRAY结构体内pvData数组的大小

解决方案

你原有实现的核心问题是将tagSAFEARRAY的pvData字段直接定义为固定长度的c_int16数组,不符合C侧的原始定义:C代码中pvData是指向数据缓冲区的void*指针,并非结构体内嵌的固定长度数组,所以无法直接通过修改结构体字段定义实现动态长度适配,正确调整方案如下:


步骤1:修正结构体与函数原型定义

import ctypes

myLibrary = ctypes.CDLL('library.dll')

# pvData定义为void指针,而非固定长度数组
class tagSAFEARRAY(ctypes.Structure):
    _fields_ = [("pvData", ctypes.c_void_p)]

OnLineGetData = myLibrary.OnLineGetData
# 补全原有argtypes缺失的闭合括号
OnLineGetData.argtypes = [ctypes.POINTER(ctypes.POINTER(tagSAFEARRAY))]
OnLineGetData.restype = ctypes.c_long

步骤2:调用函数并转换动态长度数组

这里默认OnLineGetData的返回值为实际返回的int16类型元素个数,若你的DLL返回值为错误码,请参考DLL文档先获取实际数据长度后再做转换:

# 初始化二级指针入参
p_safe_array = ctypes.POINTER(tagSAFEARRAY)()
# 调用DLL函数获取数据与长度
data_len = OnLineGetData(ctypes.byref(p_safe_array))

if data_len > 0:
    # 将void类型的pvData指针强制转换为对应长度的int16数组指针
    array_ptr = ctypes.cast(p_safe_array.contents.pvData, ctypes.POINTER(ctypes.c_int16 * data_len))
    # 可直接转为Python列表使用
    result_array = list(array_ptr.contents)
    
    # 【注意】内存释放规则:DLL内部申请的内存必须调用DLL配套的释放接口回收,不要直接使用ctypes.free,避免跨堆操作崩溃
    # 示例:若DLL提供释放接口OnLineFreeData,调用方式为 myLibrary.OnLineFreeData(ctypes.byref(p_safe_array))

特殊场景适配

如果OnLineGetData的返回值为错误码,不直接返回数据长度,可按照DLL设计的常规流程处理:

  • 第一次调用OnLineGetData时传空指针,获取需要的缓冲区长度
  • 按照长度准备好对应空间后,第二次调用接口获取实际数据
  • 重复上述指针转换逻辑即可拿到对应长度的数组

内容的提问来源于stack exchange,提问作者Javier Pina De Paz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:12:03