Delphi 当从不同的模块传递实例时,为什么is运算符无法返回我期望的结果?

Delphi 当从不同的模块传递实例时,为什么is运算符无法返回我期望的结果?,delphi,dll,fastmm,Delphi,Dll,Fastmm,我从事Delphi项目,与许多其他小型库进行交互。 我使用FastMM4,我想处理通过dll参数传递的复杂类 例如,我将表单发送到我的dll。在dll中,我使用运算符“IS”测试参数的类型 但在Dll中,运算符“IS”始终返回“false” 例 library Dll; uses FastMM4, System.SysUtils, System.Classes, Vcl.Dialogs, Vcl.Forms; {$R *.res} proc

我从事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;

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

即使在您修复该问题时,
is
运算符的明显错误行为也是意料之中的。您的流程中有两个VCL实例。一个在主机中,一个在DLL中。它们都有VCL中定义的类的不同版本。因此,DLL的
TForm
与主机中的
TForm
是不同的类。这就是为什么
的计算结果为假

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

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


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

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

即使在您修复该问题时,
is
运算符的明显错误行为也是意料之中的。您的流程中有两个VCL实例。一个在主机中,一个在DLL中。它们都有VCL中定义的类的不同版本。因此,DLL的
TForm
与主机中的
TForm
是不同的类。这就是为什么
的计算结果为假

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

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


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

注意呼叫约定。您的声明彼此不匹配。是的,当然我在上一次的示例中更改了reduce代码。抱歉,这真的是“Proc:procedure(l:TObject)”注意调用约定。您的声明彼此不匹配。是的,当然我在上一次的示例中更改了reduce代码。抱歉,这真的是“Proc:procedure(l:TObject)