在使用package编译的dll和没有它们编译的dll之间处理回调方法是安全的(Delphi)?

Vic*_*tor 3 delphi dll callback

我正在使用Delphi 2007,我有这样的情况:

{ CommonUnit.pas }
type
  // there is a callback which I want to process
  TFooBar = procedure(Sender: IInterface) of object; stdcall;

  // there is an interface which is used by all modules
  IFoo = interface
  ['{0FAA4B2B-E82A-4A2A-B55F-C75EC53A1318}']
    procedure Bar(Callback: TFooBar); stdcall;
  end;

{ UnitInModuleCompiledWithoutPackages.pas }
type
  // there is a class which implements IFoo
  // and it's defined in Module One compiled without packages
  TFoo = class(TInterfacedObject, IFoo)
  public
    // implementation is ommited
    procedure Bar(Callback: TFooBar); stdcall;
  end;

{ UnitInModuleCompiledWithPackages.pas }
// there is a code in Module Two compiled with packages
type
  TSomeClass = class
  public
    // implementation is ommited
    procedure SomeMethod(Sender: IInterface); stdcall;
  end;

var
  SomeObject: TSomeClass; // assigned by somehow
  Foo: IFoo; // assigned by somehow

begin
  // ...
  Foo.Bar(SomeObject.SomeMethod); // so it is safe?
  // ...
end;
Run Code Online (Sandbox Code Playgroud)

我知道在我的情况下,当我尝试传递对象引用时,Foo.Bar如果它被声明为这样,那将是一个内存损坏:

type
  IFoo = interface
  ['{0FAA4B2B-E82A-4A2A-B55F-C75EC53A1318}']
    // TSomeClass now declared in CommonUnit.pas
    procedure Bar(CallbackObject: TSomeClass); stdcall;
  end;
Run Code Online (Sandbox Code Playgroud)

这是因为TSomeClass模块一的实现与模块二(不同的内存管理器等)不同.
但是方法参考怎么样?
我没有在Embarcadero的文档中找到任何可能是为了清理这些东西.

Dav*_*nan 5

你的代码很好.当你传递方法指针TFooBar时,你传递两个指针,一个函数指针和一个实例指针.当您调用该方法时,所有版本的Delphi都会执行完全相同的操作来调用该方法,因为调用约定强制执行精确的二进制接口.并且所有版本的Delphi都以相同的方式表示方法指针.

您关心的问题是:

  1. 不同的记忆经理.没问题,因为我们没有进行堆分配.
  2. 不同编译器上的不同对象表示.这里没问题,因为调用方法指针不依赖于对象表示.它依赖于代码指针和数据指针(通过模块之间的值传递)和调用约定(按照约定同意相同).