Kevin Black
Kevin Black

Reputation: 119

Passing Pointer from C++ to Delphi DLL

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: enter image description here

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

Answers (1)

Remy Lebeau
Remy Lebeau

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

Related Questions