如何在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,判定为结构体或指针传递错误。
错误原因
- 结构体类型不匹配:Delphi中用
class定义SSP_COMMAND,而C的struct是值类型,Delphi的class是引用类型,自带虚表指针,内存布局与C结构体完全不同,导致成员偏移解析错误。 - 成员类型错误:
- C++的
unsigned long对应Delphi的Cardinal,用户误用Integer; - C++的
unsigned char对应Delphi的Byte,用户误用Integer;
类型大小不一致引发内存对齐错误,参数值被DLL错误解析。
- C++的
- 函数参数定义错误: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
相关产品推荐
相关产品推荐

