我搜索过,找不到任何能回答我问题的内容。如果我的问题的措词不正确,请提出建议,我会重新措辞。我并不自称是指针专家,但我所做的似乎相当直接,并且在此处提供的指导中:
Pointers and Pointer Types (Delphi)
我有一个用Delphi编写的DLL。它是从C ++应用程序(sfms_trayicon.exe)调用的。有问题的函数是Pointer类型,它有一个参数,一个指针。指针作为通用指针传递,然后转换为hWnd指针。然后取消引用hWnd类型的变量。这是实际的功能代码:
function sfms_ui_init(FhWnd: Pointer): Pointer;
var
pCallinghWnd: ^hWnd; // hWnd pointer type
begin
try
// Get the hWnd passed as a generic pointer
pCallinghWnd := FhWnd; // Cast the general pointer to a hWnd pointer
CallinghWnd := pCallinghWnd^; // De-reference the pointer (CallinghWnd is a global var of type hWnd)
finally
end;
end;
传递给函数的指针有效。对hWnd指针类型的赋值有效。取消引用偶尔会起作用,但大多数时候生成和访问违规:
我的问题,我希望它足够具体,为什么行引用指针偶尔工作,但大多数时候会抛出访问冲突? 我想接下来会是,我需要做些什么才能让它发挥作用?
由于
答案 0 :(得分:3)
Delphi和C ++是强类型语言。由于您的函数需要一个指向HWND
的指针作为输入,因此请将其声明为,例如:
type
PHWND = ^HWND;
function sfms_ui_init(FhWnd: PHWND): Pointer;
begin
CallinghWnd := FhWnd^;
//...
end;
或更好:
function sfms_ui_init(var FhWnd: HWND): Pointer;
begin
CallinghWnd := FhWnd;
//...
end;
通过指针/引用传递HWND
变量没有意义,除非函数需要直接修改调用者的HWND
变量。 HWND
已经是指针,因此在大多数情况下应该按值传递:
function sfms_ui_init(FhWnd: HWND): Pointer;
begin
CallinghWnd := FhWnd;
//...
end;
为什么取消引用指针的行偶尔会工作,但大多数情况下会引发访问冲突?我想接下来会是,我需要做些什么才能让它发挥作用?
没有看到你的C ++代码,就没有办法真正回答这个问题。但是,由于您的函数需要指向 HWND
的指针,但是将其作为通用无类型Pointer
接受,因此C ++代码可能无法将正确的内存地址传递给那个指针。例如,如果C ++代码执行此操作:
HWND hWnd = ...;
sfms_ui_init(hWnd); // passing wrong address!
当它应该这样做时:
HWND hWnd = ...;
sfms_ui_init(&hWnd); // passing correct address!
Delphi中的 Pointer
转换为C ++中的void*
,它没有类型信息。 HWND
已经是指针,任何指针都可以传递给void*
,因此编译器允许赋值,但会导致运行时错误。
更有理由去除无类型指针并改为使用类型指针。使用适当的类型可以让C ++编译器验证正确的指针值是否传递给函数,例如:
// given: function sfms_ui_init(FhWnd: PHWND): Pointer;
// or: function sfms_ui_init(var FhWnd: HWND): Pointer;
HWND hWnd = ...;
sfms_ui_init(hWnd); // compiler error!
sfms_ui_init(&hWnd); // OK
// given: function sfms_ui_init(FhWnd: HWND): Pointer;
HWND hWnd = ...;
sfms_ui_init(hWnd); // OK
sfms_ui_init(&hWnd); // compiler error!