将指针从C ++传递到Delphi DLL

时间:2016-01-06 14:00:58

标签: function delphi pointers dll

我搜索过,找不到任何能回答我问题的内容。如果我的问题的措词不正确,请提出建议,我会重新措辞。我并不自称是指针专家,但我所做的似乎相当直接,并且在此处提供的指导中:

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指针类型的赋值有效。取消引用偶尔会起作用,但大多数时候生成和访问违规: enter image description here

我的问题,我希望它足够具体,为什么行引用指针偶尔工作,但大多数时候会抛出访问冲突? 我想接下来会是,我需要做些什么才能让它发挥作用?

由于

1 个答案:

答案 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!