释放 OleVariant 后面的接口的正确方法是什么?

发布于 2024-11-25 07:04:55 字数 899 浏览 3 评论 0原文

我正在尝试找到一种安全/确定性的方法来释放封装在 OleVariant 中的接口。

AFAICS Delphi 在过程结束时释放接口引用,但就我而言,我必须更早执行此操作,因为我必须关闭 COM。

procedure Test;
var
  LLibrary: OleVariant;
begin
  CoInitialize(nil);
  try
    LLibrary := Null;
    try
      LLibrary := CreateOleObject(LibraryName);
    finally
      LLibrary := Unassigned; // <-- I would like to release the interface here
    end;
  finally
    CoUninitialize; // <-- Shutdown of COM
  end;
end; // <-- The compiler releases the interface here

我想将 OleVariant 放入一个额外的类实例中,在调用 CoUninitialize 之前可以释放该实例。

procedure Test;
var
  Container: TLibraryContainer; // Holds the OleVariant
begin
  CoInitialize(nil);
  try
    Container := TLibraryContainer.Create;
    try
      {...}
    finally
      Container.Free;
    end;
  finally
    CoUninitialize;
  end;
end;

这个解决方案安全吗还是有我忽略的更好的解决方案?

I am trying to find a safe/deterministic way to release an interface which is encapsulated in an OleVariant.

AFAICS Delphi releases interface references at the end of a procedure, but in my case I have to do it earlier, because I have to shut down COM.

procedure Test;
var
  LLibrary: OleVariant;
begin
  CoInitialize(nil);
  try
    LLibrary := Null;
    try
      LLibrary := CreateOleObject(LibraryName);
    finally
      LLibrary := Unassigned; // <-- I would like to release the interface here
    end;
  finally
    CoUninitialize; // <-- Shutdown of COM
  end;
end; // <-- The compiler releases the interface here

I though of putting the OleVariant in an extra class instance that I can free before I call CoUninitialize.

procedure Test;
var
  Container: TLibraryContainer; // Holds the OleVariant
begin
  CoInitialize(nil);
  try
    Container := TLibraryContainer.Create;
    try
      {...}
    finally
      Container.Free;
    end;
  finally
    CoUninitialize;
  end;
end;

Is this solution safe or is there a better solution I have overlooked?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尤怨 2024-12-02 07:04:55

编译器显然使用隐式本地接口变量作为 CreateOleObject 的返回值。然后在例程结束时释放它,这对你来说太晚了。

有几种方法可以解决这个问题。首先,您可以明确由 CreateOleObject 返回的 IDispatch 接口引用。这使您可以控制其生命周期。

procedure Test;
var
  intf: IDispatch;
  LLibrary: OleVariant;
begin
  CoInitialize(nil);
  try
    intf := CreateOleObject(LibraryName);
    try
      LLibrary := intf;
    finally
      VarClear(LLibrary);
      intf := nil;
    end;
  finally
    CoUninitialize;
  end;
end;

另一种方法是将调用 CreateOleObject 的代码移至具有自己作用域的单独例程中。

procedure DoWork;
var
  LLibrary: OleVariant;
begin
  LLibrary := CreateOleObject(LibraryName);
  //do stuff with LLibrary
end;

procedure Test;
begin
  CoInitialize(nil);
  try
    DoWork;
  finally
    CoUninitialize;
  end;
end;

由于隐式本地引用位于 DoWork 范围内,因此它会在 DoWork 结束时释放,因此在运行 CoUninitialize 之前释放。

我的建议是使用第二个选项,它更干净,并强制编译器代表您完成工作。

The compiler is clearly using an implicit local interface variable for the return value from CreateOleObject. This is then released at the end of the routine, too late for you.

There are a couple of ways to defeat this. First of all you could be explicit about the IDispatch interface reference returned by CreateOleObject. This allows you to control its lifetime.

procedure Test;
var
  intf: IDispatch;
  LLibrary: OleVariant;
begin
  CoInitialize(nil);
  try
    intf := CreateOleObject(LibraryName);
    try
      LLibrary := intf;
    finally
      VarClear(LLibrary);
      intf := nil;
    end;
  finally
    CoUninitialize;
  end;
end;

An alternative would be to move the code that called CreateOleObject into a separate routine with its own scope.

procedure DoWork;
var
  LLibrary: OleVariant;
begin
  LLibrary := CreateOleObject(LibraryName);
  //do stuff with LLibrary
end;

procedure Test;
begin
  CoInitialize(nil);
  try
    DoWork;
  finally
    CoUninitialize;
  end;
end;

Since the implicit local reference is within the scope of DoWork it is released at the end of DoWork and therefore before you run CoUninitialize.

My recommendation is to use the second option which is cleaner and forces the compiler to do the work on your behalf.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文