使用Python ctypes向LabVIEW生成的DLL传递Path类型参数报错
用Python ctypes调用LabVIEW生成的DLL传递文件路径报错解决方案
问题场景
已实现用Python ctypes调用LabVIEW生成的C调用约定DLL,能正常传递整数、字符串参数,但传递文件路径时触发内存访问错误:
OSError: exception: access violation reading 0x003A0043
头文件中ReadFile函数参数为Path *FilePath,尝试用ctypes.c_char_p传入字节串失败。
头文件内容
#include "extcode.h" #pragma pack(push) #pragma pack(1) #ifdef __cplusplus extern "C" { #endif /*! * ReadFile */ void __cdecl ReadFile(Path *FilePath); MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module); #ifdef __cplusplus } // extern "C" #endif #pragma pack(pop)
原Python代码
import ctypes dll = ctypes.cdll.LoadLibrary("C:\LabVIEW 2016\Misc\DLL Test\Builds\Build2\Build2.dll") dll.ReadFile.argtypes = (ctypes.c_char_p,) dll.ReadFile.restype = None FilePath = b"C:\Users\gjacob\Desktop\File Parking\thorlabs order.txt" dll.ReadFile(FilePath)
问题原因
LabVIEW的Path是自定义结构体,并非普通C字符串指针。Path结构体包含字符串长度、字符缓冲区等字段,直接传入c_char_p类型的指针会导致DLL尝试读取非预期的内存结构,引发访问违规。
解决步骤
- 定义LabVIEW Path结构体
根据LabVIEW的extcode.h定义,Path结构体需匹配头文件的1字节对齐要求:
class Path(ctypes.Structure): _pack_ = 1 # 对应头文件的#pragma pack(1) _fields_ = [ ("cnt", ctypes.c_int32), # 路径字符串长度(不含终止符) ("buf", ctypes.c_char * 1) # 柔性数组,实际存储路径字符 ]
- 构造Path实例并填充路径
动态分配结构体内存,将路径字节串复制到缓冲区:
def create_labview_path(path_bytes): # 计算总内存:结构体头部 + 路径字节长度 total_size = ctypes.sizeof(Path) + len(path_bytes) # 分配内存并转换为Path指针 path_ptr = ctypes.cast(ctypes.create_string_buffer(total_size), ctypes.POINTER(Path)) # 设置路径长度 path_ptr.contents.cnt = len(path_bytes) # 复制路径内容到缓冲区 ctypes.memmove(ctypes.addressof(path_ptr.contents.buf), path_bytes, len(path_bytes)) return path_ptr
- 修改Python调用代码
更新参数类型定义,使用构造好的Path指针调用函数:
import ctypes class Path(ctypes.Structure): _pack_ = 1 _fields_ = [ ("cnt", ctypes.c_int32), ("buf", ctypes.c_char * 1) ] def create_labview_path(path_bytes): total_size = ctypes.sizeof(Path) + len(path_bytes) path_ptr = ctypes.cast(ctypes.create_string_buffer(total_size), ctypes.POINTER(Path)) path_ptr.contents.cnt = len(path_bytes) ctypes.memmove(ctypes.addressof(path_ptr.contents.buf), path_bytes, len(path_bytes)) return path_ptr # 加载DLL,用原始字符串避免转义问题 dll = ctypes.cdll.LoadLibrary(r"C:\LabVIEW 2016\Misc\DLL Test\Builds\Build2\Build2.dll") dll.ReadFile.argtypes = (ctypes.POINTER(Path),) dll.ReadFile.restype = None # 构造路径字节串,注意转义反斜杠或用原始字符串编码 file_path = b"C:\\Users\\gjacob\\Desktop\\File Parking\\thorlabs order.txt" lv_path = create_labview_path(file_path) dll.ReadFile(lv_path)
额外注意事项
- 路径编码需匹配DLL处理逻辑,LabVIEW默认多为UTF-8或系统编码
- 路径字符串推荐用原始字符串前缀
r再编码为字节串,避免转义错误 - 若DLL需要宽字符路径,需将结构体字段改为
c_wchar类型,传递宽字节串
内容的提问来源于stack exchange,提问作者gjacob
相关产品推荐
相关产品推荐

