Reputation: 119
I have searched and cannot find anything that answers my question. If the phrasing of my question is incorrect please advise and I will rephrase it. I do not profess to be an expert in pointers, but what I am doing seems fairly straight forward and within the guidance provided here:
Pointers and Pointer Types (Delphi)
I have a DLL written in Delphi. It is called from a C++ application (sfms_trayicon.exe). The function in question is of type Pointer and it has one parameter, a pointer. The pointer is passed as a generic pointer and then cast to a hWnd pointer. It is then de-referenced to a variable of type hWnd. Here is the actual function code:
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;
The pointer passed to the function is valid. The assignment to a hWnd pointer type works. The de-referncing occasionally works, but most times generates and access violation:
My question, and I hope it is specific enough, why would the line de-referencing the pointer work occasionally, but most times throw an access violation? I guess the follow up would be, what do I need to do to make it work?
Thanks
Upvotes: 0
Views: 843
Reputation: 595339
Delphi and C++ are strongly-typed languages. Since your function expects a pointer to an HWND
as input, declare it as such, eg:
type
PHWND = ^HWND;
function sfms_ui_init(FhWnd: PHWND): Pointer;
begin
CallinghWnd := FhWnd^;
//...
end;
Or better:
function sfms_ui_init(var FhWnd: HWND): Pointer;
begin
CallinghWnd := FhWnd;
//...
end;
There is no point in passing an HWND
variable by pointer/reference, unless the function needs to modify the caller's HWND
variable directly. An HWND
is already a pointer, so it should be passed by value in most cases:
function sfms_ui_init(FhWnd: HWND): Pointer;
begin
CallinghWnd := FhWnd;
//...
end;
why would the line de-referencing the pointer work occasionally, but most times throw an access violation? I guess the follow up would be, what do I need to do to make it work?
Without seeing your C++ code, there is no way to really answer that. However, since your function expects a pointer to an HWND
, but is accepting it as a generic untyped Pointer
, chances are the C++ code is not passing the correct memory address to that pointer. For instance, if the C++ code is doing this:
HWND hWnd = ...;
sfms_ui_init(hWnd); // passing wrong address!
When it should be doing this instead:
HWND hWnd = ...;
sfms_ui_init(&hWnd); // passing correct address!
Pointer
in Delphi translates to void*
in C++, which has no type information. An HWND
is already a pointer, and any pointer can be passed to a void*
, so the compiler allows the assignment, but it causes a runtime error.
All the more reason to get rid of untyped pointers and use typed pointers instead. Using proper types lets the C++ compiler validate that the correct kind of pointer value is being passed to the function, eg:
// 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!
Upvotes: 3