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

Delphi 11调用带int*参数的C DLL函数访问违规问题咨询

核心错误原因

你遇到崩溃/访问违规是三个问题叠加导致的:

  • 第一个参数char* nomed是输出缓冲区,不是输入参数。DLL会往这个地址写入返回的目标名称字符串,你现在传的是从空String转来的临时AnsiString指针,没有预留任何可写入的内存空间,DLL一写就越界,这是最主要的崩溃原因。
  • 包装函数的Count参数是值传递,你在函数里取@Count拿到的是函数内部形参临时副本的地址,DLL改这个地址的值,外层调用的count变量根本拿不到结果,还可能破坏栈内存。
  • 调用约定可能不匹配。C语言编译的DLL如果没显式写__stdcall,默认是cdecl约定,你现在声明成stdcall会导致栈指针恢复错误,出现随机崩溃。
正确调用实现
  1. 先修正DLL导入声明,用var参数传int*更稳妥,避免手动操作指针出错:
const
  QUODLL = 'PcQuoDllNoWrap.dll';

// 注意:如果按stdcall调用出现返回值错乱、栈异常,把stdcall换成cdecl即可
function sendQuoGetInfDstn(nomed: PAnsiChar; var rigd: Integer): Integer; stdcall; external QUODLL;
  1. 写包装函数时,必须给第一个参数预分配足够的固定长度缓冲区,同时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;
  1. 调用时注意字符集匹配,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 10:15:30