Delphi调用LabVIEW DLL传字符串触发Access Violation问题求助
报错核心原因
触发Access Violation是三个不匹配问题叠加导致的,数学运算类DLL调用正常是因为数值类型参数在stdcall约定下只要宽度匹配很少出现栈错位,字符串传参只要签名、类型、内存任意一环出错就会直接崩溃:
- 函数签名完全不匹配:DLL导出函数是2个入参、void无返回值,原Delphi端声明的是1个入参、PChar返回值,调用时栈排布完全错误,函数返回时会直接跳转到非法内存地址触发违例。
- 字符串类型内存布局不兼容:LabVIEW的
PStr是Pascal风格短字符串,内存结构为「1字节长度值 + 最多255字节ANSI字符内容,无NULL终止符」;Delphi的PChar是C风格NULL结尾字符串指针,内存布局完全不匹配,传过去后LabVIEW读到的长度值是非法值,会直接越界访问内存。 - 输出参数内存未提前分配:DLL的第二个参数是输出缓冲区,要求调用方提前申请好足够的内存空间供DLL写入,原代码根本没有给输出参数预留合法内存,还错误把函数按返回指针的形式调用,必然触发内存访问错误。
修复方案
前置类型对齐
LabVIEW的PStr和Delphi原生ShortString内存布局100%匹配,直接用ShortString做参数载体即可,不需要手动构造结构体。
修正函数声明
严格对齐DLL导出的函数签名:两个PLVStr(即^ShortString)入参,无返回值,stdcall调用约定。
正确调用逻辑
提前初始化输入、输出字符串(Delphi会自动为ShortString分配256字节空间,完全满足PStr最大长度要求),传变量地址给DLL,调用完成后直接读取输出字符串即可。
修正后完整代码
type PLVStr = ^ShortString; TReadStringWriteFunc = procedure(String_input: PLVStr; String_output: PLVStr); stdcall; var hDll: THandle; strInput, strOutput: ShortString; fReadString: TReadStringWriteFunc; begin hDll := LoadLibrary('C:\Interface.dll'); if hDll = 0 then Exit; // 原代码hbar>=32的判断是Win16时代遗留写法,32/64位下判断是否为0即可 try fReadString := GetProcAddress(hDll, 'Read_String_In_Write_String_Out'); if not Assigned(fReadString) then Exit; strInput := 'test'; strOutput := ''; // 初始化输出缓冲区 fReadString(@strInput, @strOutput); // 此处strOutput即为DLL返回的原字符串,可直接使用 ShowMessage(strOutput); finally FreeLibrary(hDll); end; end;
额外注意事项
- 平台架构必须匹配:如果LabVIEW生成的是32位DLL,Delphi编译目标必须选32位;如果是64位DLL则必须选64位平台,跨架构加载DLL会直接失败。
- 不要尝试接收DLL返回的字符串指针:LabVIEW自行管理内部内存堆,跨模块返回的字符串指针随时可能被LabVIEW内存回收,直接访问必然出问题,必须用「调用方分配缓冲区、DLL填充内容」的方式传参。
- 如果后续需要传递长度超过255的字符串,LabVIEW对应的类型是LStr(长字符串),内存结构是4字节长度+后续字符内容,可自定义数组结构映射,本次可行性测试用的PStr用ShortString即可满足要求。
内容的提问来源于stack exchange,提问作者Shawn Vance
相关产品推荐
相关产品推荐

