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

如何在Delphi中正确调用C++ DLL的OpenSSPComPort函数?

Delphi调用C++ DLL的OpenSSPComPort函数问题解决方法

问题背景

C++ DLL中的函数与结构体定义如下:

#define CCONV _stdcall 
typedef struct{ 
    unsigned long BaudRate; 
    unsigned char PortNumber; 
    // 其他成员
}SSP_COMMAND;

NOMANGLE int CCONV OpenSSPComPort (SSP_COMMAND * cmd);

文档说明:OpenSSPComPort接收SSP_COMMAND结构体指针,返回WORD类型值,0表示失败,1表示成功。

用户在Delphi中实现后出现异常:传入PortNumber=8,但实际尝试打开COM0,判定为结构体或指针传递错误。

错误原因

  1. 结构体类型不匹配:Delphi中用class定义SSP_COMMAND,而C的struct是值类型,Delphi的class是引用类型,自带虚表指针,内存布局与C结构体完全不同,导致成员偏移解析错误。
  2. 成员类型错误:
    • C++的unsigned long对应Delphi的Cardinal,用户误用Integer;
    • C++的unsigned char对应Delphi的Byte,用户误用Integer;
      类型大小不一致引发内存对齐错误,参数值被DLL错误解析。
  3. 函数参数定义错误:C++函数接收结构体指针,用户的Delphi函数直接传SSP_COMMAND类实例,虽class是引用传递,但因内存布局错误,实际传递的指针指向的数据不符合DLL预期。

修正后的Delphi代码

type
  // 用record严格匹配C++的struct,成员类型、顺序完全对齐
  SSP_COMMAND = record
    BaudRate: Cardinal;   // 对应C++ unsigned long
    PortNumber: Byte;     // 对应C++ unsigned char
    // 其他成员需与C++结构体定义完全一致
  end;

type
  // 函数定义为接收结构体指针,匹配C++的SSP_COMMAND*
  TOpenSSPComPort = function(var cmd: SSP_COMMAND): Integer; stdcall;
  // 也可使用指针形式:function(cmd: PSSP_COMMAND): Integer; stdcall;

var
  nv11: THandle;
  OpenSSPComPort: TOpenSSPComPort;
  ss_cmd: SSP_COMMAND; // record为值类型,无需Create

procedure TForm1.FormCreate(Sender: TObject);
begin
  if nv11 = 0 then
  begin
    nv11 := LoadLibrary(PChar('ITLSSPProc.dll'));
    if nv11 <> 0 then
      @OpenSSPComPort := GetProcAddress(nv11, 'OpenSSPComPort');
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if not Assigned(OpenSSPComPort) then
  begin
    Memo1.Lines.Add('未成功加载DLL函数');
    Exit;
  end;

  // 先清零结构体避免垃圾数据干扰
  FillChar(ss_cmd, SizeOf(SSP_COMMAND), 0);
  ss_cmd.BaudRate := 9600;
  ss_cmd.PortNumber := 8;

  if OpenSSPComPort(ss_cmd) = 0 then
    Memo1.Lines.Add('Error OpenSSPComPort')
  else
    Memo1.Lines.Add('OpenSSPComPort - OK');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if nv11 <> 0 then
    FreeLibrary(nv11); // 退出时释放DLL句柄
end;

补充说明

  • 若使用指针形式的函数定义,调用时需传递结构体指针:
    type
      TOpenSSPComPort = function(cmd: PSSP_COMMAND): Integer; stdcall;
    // 调用代码
    if OpenSSPComPort(@ss_cmd) = 0 then ...
    
  • 结构体所有成员必须与C++定义完全一致,包括顺序、类型和内存对齐规则,否则仍会出现参数解析错误。

内容的提问来源于stack exchange,提问作者Alexander Rogan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:39:27