1

我从事与许多其他小型库交互的 Delphi 项目。我使用 FastMM4,我想处理通过 dll 参数传递的复杂类。

例如,我将表单发送到我的 dll。在 dll 中,我使用运算符“IS”测试参数的类型。

但是进入 Dll 的操作符“IS”总是返回“false”

示例

library Dll;

uses
     FastMM4,
     System.SysUtils,
     System.Classes,
     Vcl.Dialogs,
     Vcl.Forms;

{$R *.res}

procedure Complex(L : TObject);stdcall;
begin
     if L is TForm then
        showmessage('Ok')
     else
        showmessage('Pas ok') ;

     if L is TCustomFrame then
         showmessage('Ok')
     else
         showmessage('Pas ok')
end;

exports
  Complex;

begin
end.

和电话

procedure TffsIsOperator.Button2Click(Sender: TObject);
var
 MaDLL : THandle;
 Proc  : procedure (l : TObject);
begin
   try
      MaDLL := LoadLibrary(PChar('Dll.dll'));
      @Proc := GetProcAddress(MaDLL, 'Complex');
      Proc(self);
   finally
      FreeLibrary(MaDLL);
   end;
end;
4

1 回答 1

6

首先,你有一个调用约定不匹配。您必须通过使互操作边界两侧的调用约定相同来解决此问题。

即使您解决了这个问题,is操作员的明显不当行为也是意料之中的。您的流程中有两个 VCL 实例。一个在主机中,一个在 DLL 中。它们每个都有 VCL 中定义的类的不同版本。因此,DLLTForm是与主机中不同的类TForm。这就是为什么is评估为假的原因。

处理此问题的传统方法是安排您的流程中只有一个 RTL/VCL 实例。您可以通过使用运行时包来实现这一点。

如果运行时包对您来说不是一个可行的选择,并且您必须使用 DLL,那么您将不得不放弃通过 DLL 边界传递任何 Delphi 类。我完全认为这是不受欢迎的消息,但事实就是如此。您不能TObject跨 DLL 边界传递实例并尝试调用方法、查询类型标识等。DLL 根本不支持这些。仅适用于运行时包。

因此,如果您必须使用 DLL,那么您需要坚持使用简单类型。整数、浮点值、字符类型、数组(但不是动态数组)、记录、指向此类类型的指针、接口。作为一个简单的经验法则,如果您在 Win32 中找不到建议的互操作示例,那么它可能是无效的。

于 2014-06-10T15:32:38.540 回答