跨语言编程时,经常要传递数据结构,尤其是窗口句柄(HWND)等。本文将介绍如何将 Delphi 7 中的 HWND 传递到 C++ DLL 中。
理解调用约定
调用约定决定了函数参数如何传递以及函数返回值如何处理。不同的编译器和语言可能使用不同的调用约定,这会导致参数传递不匹配。
Delphi 默认使用 register
调用约定,而 Visual Studio C++ 默认使用 __cdecl
。register
将参数保存在寄存器中,而 __cdecl
将参数通过栈传递。由于两种调用约定的差异,导致 Delphi 无法正确将 HWND 传递给 C++ DLL。
解决方法:指定调用约定
需要在 Delphi 侧显式指定调用约定为 cdecl
,使 Delphi 按照 C++ DLL 的预期方式传递参数。在 Delphi 代码中,将导入 DLL 函数的声明修改为:
function setGlRenderTo (handler : HWND) : integer; cdecl; external 'qmm.dll';
cdecl
关键字指定了函数的调用约定。然后重新编译并链接 Delphi 项目,让更改后的代码生效。
代码示例
Delphi 代码:
unit Unit1;
interface
uses
Windows,
Messages,
SysUtils,
Variants,
Classes,
Graphics,
Controls,
Forms,
Dialogs;
// 定义窗体类
type
TForm1 = class(TForm)
// 按钮点击事件处理程序
procedure Button1Click(Sender: TObject);
private
{ Private declarations } // 私有声明部分
public
{ Public declarations } // 公共声明部分
end;
// 声明窗体变量
var
Form1: TForm1;
implementation
{$R *.dfm}
// 声明外部 DLL 函数
// 该函数接受一个 HWND 类型的参数,并返回一个整数值
// cdecl 指示使用 C 语言调用约定,external 指定函数位于 qmm.dll 库中
function setGlRenderTo(handler: HWND): Integer; cdecl; external 'qmm.dll';
// 按钮点击事件处理程序
procedure TForm1.Button1Click(Sender: TObject);
begin
// 调用 setGlRenderTo 函数,将窗体的句柄传递给它
setGlRenderTo(Handle);
end;
end.
C++ 代码:
#include <windows.h>
int setGlRenderTo(HWND handler) {
// 使用 handler 进行相关操作
return 0;
}
总结
通过显式指定调用约定,可以解决 Delphi 7 传递 HWND 到 C++ DLL 的问题。在进行跨语言编程时,需注意调用约定,并确保双方使用相同的约定以避免数据传递错误。