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

使用Ctypes封装DLL遇断言失败(string != NULL)问题求助

解决Ctypes调用DLL时sprintf的NULL指针断言错误

首先,你的问题出在不必要的指针转换上——你不需要用addressof和cast来传递字符串缓冲区,create_string_buffer返回的对象本身就可以直接作为char*指针传入DLL函数。

修复后的完整代码

import ctypes
from ctypes import c_double, POINTER

# 加载并配置DLL
dll = ctypes.WinDLL("MyDLL.dll")
f = dll.compute_result
f.restype = c_double
f.argtypes = [c_double, c_double, POINTER(ctypes.c_char), POINTER(ctypes.c_char)]

# 输入变量
var1 = 1.1
var2 = 2.2

# 创建足够大的字符串缓冲区
size = 1024
buf1 = ctypes.create_string_buffer(size)
buf2 = ctypes.create_string_buffer(size)

# 直接传递缓冲区对象,无需额外转换
result = f(var1, var2, buf1, buf2)

# 读取并解码输出消息
print("Output Message 1:", buf1.value.decode('utf-8'))
print("Output Message 2:", buf2.value.decode('utf-8'))
print("Computed Result:", result)

错误原因解释

你之前用cast(addressof(buf1), POINTER(c_char))的操作完全是画蛇添足:

  • create_string_buffer返回的是ctypes.c_char_Array_xxx类型的对象,当你把它直接传递给需要POINTER(c_char)的函数时,ctypes会自动将其转换为指向数组首元素的有效指针(也就是C语言里的char*)。
  • 多余的addressof和cast操作反而破坏了ctypes的自动类型转换逻辑,导致传入了无效的空指针,触发了sprintf函数的string != NULL断言检查。

额外注意事项

  1. 确保DLL函数导出正确:如果你的DLL是用C编译的,必须用extern "C"修饰函数,避免C的名字修饰(name mangling),否则Python会找不到compute_result函数:
extern "C" __declspec(dllexport) double compute_result(double var1, double var2, char *output_message1, char *output_message2){
    double result = var1 + var2;
    snprintf(output_message1, 1024, "useful output message 1");
    snprintf(output_message2, 1024, "useful output message 2");
    return result;
}
  1. 替换不安全的sprintf:建议把C++代码里的sprintf换成snprintf,明确指定缓冲区大小,避免潜在的缓冲区溢出风险。
  2. 编码匹配:因为你用的是c_char(对应C的char类型),DLL输出的是ASCII/UTF-8编码的字符串,Python读取时需要用decode('utf-8')转换为原生字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:41:24