Python调用Autel红外SDK DLL触发STATUS_STACK_BUFFER_OVERRUN异常求助
Python调用Autel红外温度解析SDK栈缓冲区溢出问题修复
调用Autel红外温度解析SDK的DLL时,程序在函数返回前崩溃,Windows错误日志显示异常为STATUS_STACK_BUFFER_OVERRUN,推测是传入变量的类型/大小与SDK定义不匹配。以下是问题代码及修复方案:
问题代码
import ctypes import numpy as np import faulthandler faulthandler.enable() sdk_path = 'dependencies/autel/AutelIrTempParserSDK.dll' ir_temp_parse = ctypes.CDLL(sdk_path) # Define the data structures class Autel_IR_INFO_S(ctypes.Structure): _fields_ = [ ('tag', ctypes.c_uint16), ('len', ctypes.c_uint16), ('show_value', ctypes.c_char * 512), ('str_value', ctypes.c_char * 512), ('num_value', ctypes.c_int) ] class QPointF(ctypes.Structure): _fields_ = [ ('x', ctypes.c_int), ('y', ctypes.c_int) ] class TempStatInfo(ctypes.Structure): _fields_ = [ ('max', ctypes.c_float), ('min', ctypes.c_float), ('avg', ctypes.c_float), ('maxPoint', QPointF), ('minPoint', QPointF) ] # Define the function prototypes ir_temp_parse.GetIrPhotoTempInfo.argtypes = [ ctypes.c_char_p, # filepath ctypes.c_int, # w ctypes.c_int, # h ctypes.POINTER(TempStatInfo), # tempStatInfo ctypes.POINTER(ctypes.c_void_p), # result (map<string, Autel_IR_INFO_S>) ctypes.POINTER(ctypes.POINTER(ctypes.c_float)) # tempArray (2D array) ] ir_temp_parse.GetIrPhotoTempInfo.restype = ctypes.c_int ir_temp_parse.GetRawTempData.argtypes = [ ctypes.c_char_p, # filepath ctypes.c_int, # w ctypes.c_int, # h ctypes.POINTER(ctypes.c_int16) # rawTempData ] ir_temp_parse.GetRawTempData.restype = ctypes.c_int filepath = b'images/autel/IRX_0001_south.jpg' w, h = 640, 512 tempStatInfo = TempStatInfo() result = ctypes.cast(ctypes.c_void_p(), ctypes.POINTER(ctypes.c_void_p)) tempArray = (ctypes.POINTER(ctypes.c_float) * h)() for i in range(h): tempArray[i] = (ctypes.c_float * w)() ret = ir_temp_parse.GetIrPhotoTempInfo(filepath, w, h, ctypes.byref(tempStatInfo), result, tempArray) if ret == 0: print("GetIrPhotoTempInfo succeeded!") # Access the results as needed else: print("GetIrPhotoTempInfo failed!") #ret = _GetRawTempData(filepath, 640, 512, rawTempData)
SDK结构定义(参考截图)
- Autel_IR_INFO_S:
tag: uint16len: uint16show_value: char[512]str_value: char[512]num_value: int
- QPointF:
x: floaty: float
- TempStatInfo:
max: floatmin: floatavg: floatmaxPoint: QPointFminPoint: QPointF
修复步骤
1. 修正QPointF结构体类型
代码中将QPointF的x和y错误定义为int类型,与SDK的float类型不符,这是栈溢出的核心原因。修改后:
class QPointF(ctypes.Structure): _fields_ = [ ('x', ctypes.c_float), ('y', ctypes.c_float) ]
2. 修正result参数初始化
原代码中result的初始化方式错误,需改为分配一个void_p变量并传递其地址:
result = ctypes.c_void_p() # 调用时传入ctypes.byref(result)
3. 优化tempArray内存分配
手动分配二维数组容易出错,改用numpy数组更安全:
tempArray = np.zeros((h, w), dtype=np.float32) tempArray_ptr = tempArray.ctypes.data_as(ctypes.POINTER(ctypes.POINTER(ctypes.c_float)))
4. 检查调用约定
若上述修改后仍崩溃,尝试将CDLL改为WinDLL(部分DLL使用stdcall约定):
ir_temp_parse = ctypes.WinDLL(sdk_path)
修改后的完整代码
import ctypes import numpy as np import faulthandler faulthandler.enable() sdk_path = 'dependencies/autel/AutelIrTempParserSDK.dll' # 尝试用WinDLL替代CDLL,根据SDK调用约定调整 ir_temp_parse = ctypes.WinDLL(sdk_path) # Define the data structures class Autel_IR_INFO_S(ctypes.Structure): _fields_ = [ ('tag', ctypes.c_uint16), ('len', ctypes.c_uint16), ('show_value', ctypes.c_char * 512), ('str_value', ctypes.c_char * 512), ('num_value', ctypes.c_int) ] class QPointF(ctypes.Structure): _fields_ = [ ('x', ctypes.c_float), ('y', ctypes.c_float) ] class TempStatInfo(ctypes.Structure): _fields_ = [ ('max', ctypes.c_float), ('min', ctypes.c_float), ('avg', ctypes.c_float), ('maxPoint', QPointF), ('minPoint', QPointF) ] # Define the function prototypes ir_temp_parse.GetIrPhotoTempInfo.argtypes = [ ctypes.c_char_p, ctypes.c_int, ctypes.c_int, ctypes.POINTER(TempStatInfo), ctypes.POINTER(ctypes.c_void_p), ctypes.POINTER(ctypes.POINTER(ctypes.c_float)) ] ir_temp_parse.GetIrPhotoTempInfo.restype = ctypes.c_int filepath = b'images/autel/IRX_0001_south.jpg' w, h = 640, 512 tempStatInfo = TempStatInfo() result = ctypes.c_void_p() # 使用numpy创建二维数组,自动管理内存 tempArray = np.zeros((h, w), dtype=np.float32) tempArray_ptr = tempArray.ctypes.data_as(ctypes.POINTER(ctypes.POINTER(ctypes.c_float))) ret = ir_temp_parse.GetIrPhotoTempInfo( filepath, w, h, ctypes.byref(tempStatInfo), ctypes.byref(result), tempArray_ptr ) if ret == 0: print("GetIrPhotoTempInfo succeeded!") # 可以直接通过tempArray访问温度数据 print(f"Max temp: {tempStatInfo.max}, Min temp: {tempStatInfo.min}, Avg temp: {tempStatInfo.avg}") else: print(f"GetIrPhotoTempInfo failed! Error code: {ret}")
内容的提问来源于stack exchange,提问作者Charlie Grove
相关产品推荐
相关产品推荐

