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

使用Python调用EPlusWth.dll时遭遇ctypes参数错误

解决EPlusWth.dll气象文件转换的ctypes调用错误

问题场景

使用Python 3.10 32位调用EnergyPlus的EPlusWth.dll,将自定义格式的气象文件批量转换为EPW格式时,出现两类错误:

  • 带byref()调用时:ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type
  • 移除byref()后:OSError: exception: access violation writing 0x00000000

原问题代码

import ctypes
from ctypes import byref, c_bool, c_char_p, c_long

conversionDLL = ctypes.WinDLL('C:/[...]/EPlusWth.dll')
conversionPrototype = ctypes.WINFUNCTYPE(
    c_bool,                    # Output type.
    c_char_p, c_long,          # Input file type and string length.
    c_char_p, c_long,          # Output file type and string length.
    c_char_p, c_long,          # Input file name and string length.
    c_char_p, c_long,          # Output file name and string length.
    c_bool,                    # Output variable ErrorFlag to use. Positive, if an error occurred.
)

conversionApiParams = (
    (1, 'strInType ', 'CUSTOM'), (1, 'InTypeLen', 0),
    (1, 'strOutType', 'EPW'), (1, 'OutTypeLen', 3),
    (1, 'strInFileName', ''), (1, 'InFileNameLen', 0),
    (1, 'strOutFileName', ''), (1, 'OutFileNameLen', 0),
    (1, 'ErrorFlag ', False),
)

conversionApi = conversionPrototype(('ProcessWeather', conversionDLL), conversionApiParams)

inputFileType =  b'CUSTOM'
outputFileType = b'EPW'
inputFileName =  b'C:/[...]/BAS_2035_RCP85_DRY.csv'
outputFileName = b'C:/[...]/BAS_2035_RCP85_DRY.epw'
errorFlag = c_bool(False)

strInType =         c_char_p(inputFileType)
strOutType =        c_char_p(outputFileType)
strInFileName =     c_char_p(inputFileName)
strOutFileName =    c_char_p(outputFileName)
InTypeLen =         c_long(len(inputFileType))
OutTypeLen =        c_long(len(outputFileType))
InFileNameLen =     c_long(len(inputFileName))
OutFileNameLen =    c_long(len(outputFileName))

conversionApi(
    byref(strInType),      byref(InTypeLen),
    byref(strOutType),     byref(OutTypeLen),
    byref(strInFileName),  byref(InFileNameLen),
    byref(strOutFileName), byref(OutFileNameLen),
    errorFlag,
)

错误原因

  1. 参数传递类型不匹配:对输入字符串参数使用byref(),导致传递了指针的指针,与函数期望的char*类型冲突。
  2. 输出参数处理错误:ErrorFlag是输出参数(函数需要修改其值),原代码直接传递值而非指针,引发内存访问违规。
  3. 默认参数干扰:通过conversionApiParams设置默认参数容易导致参数传递冲突,降低代码可靠性。

修正后的代码

import ctypes
from ctypes import byref, c_bool, c_char_p, c_long, WINFUNCTYPE, POINTER

# 加载32位EPlusWth.dll,替换为实际路径
eplus_wth_dll = ctypes.WinDLL('C:/path/to/preprocess/EPlusWth.dll')

# 定义ProcessWeather函数原型:返回值为布尔型,参数含输出用的错误标志指针
ProcessWeather = WINFUNCTYPE(
    c_bool,
    c_char_p, c_long,  # 输入文件类型、类型长度
    c_char_p, c_long,  # 输出文件类型、类型长度
    c_char_p, c_long,  # 输入文件路径、路径长度
    c_char_p, c_long,  # 输出文件路径、路径长度
    POINTER(c_bool)    # 错误标志(输出参数,需传指针)
)(('ProcessWeather', eplus_wth_dll))

# 显式声明参数类型,提升调用安全性
ProcessWeather.argtypes = [
    c_char_p, c_long,
    c_char_p, c_long,
    c_char_p, c_long,
    c_char_p, c_long,
    POINTER(c_bool)
]
ProcessWeather.restype = c_bool

# 准备参数:所有字符串用字节串,符合C语言字符串要求
input_type = b'CUSTOM'
output_type = b'EPW'
input_file = b'C:/[...]/BAS_2035_RCP85_DRY.csv'
output_file = b'C:/[...]/BAS_2035_RCP85_DRY.epw'
error_flag = c_bool(False)

# 调用函数:输入参数直接传递,错误标志传指针
conversion_success = ProcessWeather(
    input_type, len(input_type),
    output_type, len(output_type),
    input_file, len(input_file),
    output_file, len(output_file),
    byref(error_flag)
)

# 输出结果
if conversion_success:
    print("气象文件转换完成,EPW已生成")
else:
    print(f"转换失败,错误状态:{error_flag.value}")

关键调整说明

  • 移除不必要的byref():输入字符串参数直接传递字节串(ctypes会自动转换为char*),匹配函数期望的类型。
  • 修正输出参数传递:ErrorFlag改为传递指针(byref(error_flag)),确保函数能修改其值。
  • 简化函数定义:放弃默认参数设置,直接显式声明函数原型和参数类型,避免参数冲突。
  • 调用约定确认:使用WinDLL对应stdcall调用约定,符合EnergyPlus DLL的编译规范。

额外注意事项

  • 必须保证Python版本(32位)与EPlusWth.dll的位数一致。
  • 输入文件路径需确保DLL有权限访问,避免路径中包含特殊字符。
  • 若需调用SetFixOutOfRangeData,需按同样规则定义函数原型:
    # 示例:定义SetFixOutOfRangeData函数
    SetFixOutOfRangeData = WINFUNCTYPE(
        None,
        c_char_p, c_long
    )(('SetFixOutOfRangeData', eplus_wth_dll))
    # 调用:设置修复超出范围的数据
    SetFixOutOfRangeData(b'yes', len(b'yes'))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:55:02