使用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中的编码逻辑:
同时确认DLL是否要求长度包含终止符,可尝试传递write_cmd = bytes(write_cmd, 'ascii', errors='replace') + b'\0'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
相关产品推荐
相关产品推荐

