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

使用ctypes调用DLL出现Access violation错误的技术求助

问题描述

在使用Tkinter开发Python GUI程序时,调用外部DLL出现内存访问违例错误,错误信息如下:

write_flag=dfd.newp_usb_send_ascii(ctypes.c_long(deviceID),ctypes.c_char_p(cmd),ctypes.c_ulong(lengt))) OSError: exception: access violation reading 0x0000000000000081

相关代码

driver_func.py(ctypes函数定义)

newp_usb_send_ascii = cpplibrary.newp_usb_send_ascii
newp_usb_send_ascii.argtypes = (ctypes.c_long,ctypes.c_char_p,ctypes.c_ulong)
newp_usb_send_ascii.restype = ctypes.c_long

functions.py(调用函数)

import driver_func as dfd
def write(deviceID, cmd, length):
    write_flag = dfd.newp_usb_send_ascii(ctypes.c_long(deviceID),ctypes.c_char_p(cmd),ctypes.c_ulong(length))
    if write_flag != 0:
        print(f"myterminal> Write to {deviceID} not successful.\n")
    else:
        print(f"myterminal> The command {cmd} has been written to the controller successfully.\n")

GUI调用代码

def get_Text(self,event):
        write_cmd = self.entry_var.get()
        write_cmd = bytes(write_cmd,'utf-8')
        write_cmd += b'\0'
        f.write(1,write_cmd,len(write_cmd))

DLL函数定义

long EXPORT newp_usb_send_ascii (long DeviceID, char* Command, unsigned long Length);
解决方案

针对内存访问违例问题,可从以下几个方向排查修复:

  • 验证DeviceID有效性:当前传入固定值1,先调用DLL中设备枚举类函数,确认实际连接设备的有效ID,无效ID会导致DLL内部访问非法内存。
  • 简化参数传递方式:ctypes可自动将Python字节串转为c_char_p,手动构造ctypes.c_char_p(cmd)可能引发内存回收问题。修改functions.py的write函数:
    def write(deviceID, cmd, length):
        write_flag = dfd.newp_usb_send_ascii(ctypes.c_long(deviceID), cmd, ctypes.c_ulong(length))
        if write_flag != 0:
            print(f"myterminal> Write to {deviceID} not successful.\n")
        else:
            print(f"myterminal> The command {cmd} has been written to the controller successfully.\n")
    
  • 匹配DLL编码要求:函数名含ascii,说明可能要求ASCII编码而非UTF-8。修改GUI中的编码逻辑:
    write_cmd = bytes(write_cmd, 'ascii', errors='replace') + b'\0'
    
    同时确认DLL是否要求长度包含终止符,可尝试传递len(write_cmd)-1作为长度参数。
  • 修正调用约定:Windows DLL常使用stdcall调用约定,默认ctypes用cdecl,需显式指定:
    # 在driver_func.py中重新绑定函数
    newp_usb_send_ascii = ctypes.WINFUNCTYPE(ctypes.c_long, ctypes.c_long, ctypes.c_char_p, ctypes.c_ulong)(('newp_usb_send_ascii', cpplibrary))
    
  • 确保内存稳定性:将字节串转为ctypes数组,避免局部变量被提前回收:
    def get_Text(self,event):
        write_cmd = self.entry_var.get()
        write_cmd = bytes(write_cmd, 'ascii') + b'\0'
        cmd_buf = ctypes.create_string_buffer(write_cmd)
        f.write(1, cmd_buf, len(write_cmd))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:33:29