Delphi 11调用带int*参数的C DLL函数访问违规问题咨询
核心错误原因
你遇到崩溃/访问违规是三个问题叠加导致的:
- 第一个参数
char* nomed是输出缓冲区,不是输入参数。DLL会往这个地址写入返回的目标名称字符串,你现在传的是从空String转来的临时AnsiString指针,没有预留任何可写入的内存空间,DLL一写就越界,这是最主要的崩溃原因。 - 包装函数的
Count参数是值传递,你在函数里取@Count拿到的是函数内部形参临时副本的地址,DLL改这个地址的值,外层调用的count变量根本拿不到结果,还可能破坏栈内存。 - 调用约定可能不匹配。C语言编译的DLL如果没显式写
__stdcall,默认是cdecl约定,你现在声明成stdcall会导致栈指针恢复错误,出现随机崩溃。
正确调用实现
- 先修正DLL导入声明,用var参数传int*更稳妥,避免手动操作指针出错:
const QUODLL = 'PcQuoDllNoWrap.dll'; // 注意:如果按stdcall调用出现返回值错乱、栈异常,把stdcall换成cdecl即可 function sendQuoGetInfDstn(nomed: PAnsiChar; var rigd: Integer): Integer; stdcall; external QUODLL;
- 写包装函数时,必须给第一个参数预分配足够的固定长度缓冲区,同时Count参数用out/var传引用:
function TPCQuo.GetWorklistInfoTest(out Name: AnsiString; out Count: Integer): Integer; var Buffer: array[0..255] of AnsiChar; // 预分配256字节缓冲区,常规接口足够用,如果文档有明确长度按文档调整 begin // 先清空缓冲区,初始化返回值 FillChar(Buffer, SizeOf(Buffer), 0); Count := 0; Result := sendQuoGetInfDstn(@Buffer[0], Count); // 把缓冲区里的C风格字符串转成Delphi的AnsiString返回 Name := PAnsiChar(Buffer); end;
- 调用时注意字符集匹配,Delphi 11默认String是Unicode,要做对应转换:
procedure TForm1.Button4Click(Sender: TObject); var name: AnsiString; count: Integer; begin if QUO.GetWorklistInfoTest(name, count) <> 0 then ShowMessage('No worklist available ') else ShowMessage('Worklist available ' + string(name) + ' number of lines: ' + count.ToString ); end;
补充说明
- 要是按上面代码写了还是崩,优先把导入声明的
stdcall改成cdecl测试,大部分C写的工控类DLL默认都是cdecl约定。 - 如果返回的名称是乱码,确认DLL返回的字符串编码,做对应转码即可。
内容的提问来源于stack exchange,提问作者madsmailund
相关产品推荐
相关产品推荐

