【问题标题】:How to implement IOTAProjectCompileNotifier of Delphi's ToolsAPI?Delphi的ToolsAPI的IOTAProjectCompileNotifier如何实现?
【发布时间】:2011-07-23 07:38:24
【问题描述】:

我正在使用 Delphi XE IDE。我创建了一个通知器来实现 IOTACompileNotifier。在 IDE 中安装专家后。当我编译我的项目时,代码工作正常。通知程序正在为 ProjectCompileStarted 工作。

第二次编译我的项目,Delphi IDE提示:

[Fatal Error] Access violation at address 21B7FBED in module 'delphicoreide150.bpl'. Read of address 00000000

虽然我的表现看起来很奇怪:

var i: integer;
begin
  i := Project.ProjectBuilder.AddCompileNotifier(TProjectCompileNotifier.Create);
  Project.ProjectBuilder.RemoveCompileNotifier(i);
end;

在通知程序中。我只想显示无论我如何使用,ProjectBuilder 的 Add and Remove compile notifier 似乎都无法正常工作。

请告知我应该如何实施 IOTAProjectCompileNotifier。

谢谢。

这里是完整的源代码:

type
  TProjectCompileNotifier = class(TInterfacedObject, IOTAProjectCompileNotifier)
  protected
    procedure AfterCompile(var CompileInfo: TOTAProjectCompileInfo);
    procedure BeforeCompile(var CompileInfo: TOTAProjectCompileInfo);
    procedure Destroyed;
  end;

  TCompileNotifier = class(TInterfacedObject, IOTACompileNotifier)
  protected
    procedure ProjectCompileStarted(const Project: IOTAProject; Mode: TOTACompileMode);
    procedure ProjectCompileFinished(const Project: IOTAProject; Result: TOTACompileResult);
    procedure ProjectGroupCompileStarted(Mode: TOTACompileMode);
    procedure ProjectGroupCompileFinished(Result: TOTACompileResult);
  end;

procedure TCompileNotifier.ProjectCompileStarted(const Project: IOTAProject;
  Mode: TOTACompileMode);
var i: integer;
begin
  i := Project.ProjectBuilder.AddCompileNotifier(TProjectCompileNotifier.Create);
  Project.ProjectBuilder.RemoveCompileNotifier(i);
end;

var i: integer;

initialization
  i := (BorlandIDEServices as IOTACompileServices).AddNotifier(TCompileNotifier.Create);
finalization
  (BorlandIDEServices as IOTACompileServices).RemoveNotifier(i);
end.

【问题讨论】:

  • 请注意tagline advertising is not welcome here。我不会投反对票,但你应该编辑你的问题!
  • @jachguate:对不起。我从电子邮件中粘贴了问题,并没有注意到底部有签名。

标签: delphi toolsapi


【解决方案1】:

我想我可以回答这个问题。我没有 XE,所以我似乎没有 IOTAProjectCompileNotifier。但是,我的 ToolsAPI 单元中的其他 AddNotifier 方法表明它将被声明为:

function AddNotifier(const ANotifier: IOTAProjectCompileNotifier): Integer;

你这样调用这个例程:

i := Project.ProjectBuilder.AddCompileNotifier(TProjectCompileNotifier.Create);

问题是没有任何东西引用TProjectCompileNotifier.Create返回的接口。你需要这样做,像这样:

procedure TCompileNotifier.ProjectCompileStarted(const Project: IOTAProject; Mode: TOTACompileMode);
var
  i: integer;
  Intf: IOTAProjectCompileNotifier;
begin
  Intf := TProjectCompileNotifier.Create;
  i := Project.ProjectBuilder.AddCompileNotifier(Intf);
  Project.ProjectBuilder.RemoveCompileNotifier(i);
end;

您需要在初始化/完成代码中做同样的事情。

我相信这确实应该被认为是接口引用计数实现中的一个错误。已经discussed here on Stack Overflow很多次了。

【讨论】:

  • @David:我尝试了您建议的代码。我仍然遇到同样的错误。
  • @Chau 你确定 AV 发生在哪里了吗?如果您无法使用调试器,请调用 MessageBox!
  • @David:是的。我使用 OutputDebugString 来保护 IOTACompileNotifier 的所有 4 个方法。在第一次构建时,按此顺序调用的所有 4 个方法:ProjectGroupCompileStarted、ProjectCompileStarted、ProjectCompileFinished、ProjectGroupCompileFinished。在第二次构建中,我在 ProjectGroupCompileStarted 之后立即获得 AV。
  • @Chau,你在创建界面的每个地方都按照我说的做?
  • @David:是的,我已经仔细检查了我的代码。除了 OTA 源中存在错误之外,我想不出其他可能性。我在我的应用程序中经常使用 IInterface,并且知道您提到的引用计数问题。这就是为什么我对 RemoveCompileNotifier 如此敏感,否则我会忽略它。我必须看到对象在正确的位置被释放,否则会导致 IDE 运行时发生灾难性的内存泄漏。
【解决方案2】:

我想知道您为什么要从回调中删除通知程序。我可以想象 OTA 无法很好地处理这种情况。尝试以下操作:首先(在加载和初始化包时)安装 IOTAIDENotifier 以在项目打开时收到通知(在完成时将其删除)。实现其 FileNotification 以在项目打开时添加您的 IOTAProjectCompileNotifier,在项目关闭时将其删除。

【讨论】:

  • 我已经对您的建议进行了草稿测试,它似乎有效。但是,我需要大量编码才能在 FileNotification 方法中检索 IOTAProject 实例。打开项目时,我还需要缓存 (IOTAProject, Index) 列表。通过在缓存列表中查找索引来删除通知程序。
【解决方案3】:

错误代码“读取地址 00000000”可能表明您正在尝试访问不存在的资源。我看到你在 Embarcadero 论坛上问过同样的问题。就我在SO上看到的,只有几个开发者对OTA感兴趣,CG或Embarcadero的文档几乎没有,所以我建议你坚持Embarcadero的论坛。

最好的问候,
拉杜

【讨论】:

  • 我不是OTA的人,虽然有点涉猎,但是const接口参数的问题就跳出来了。它以前咬过我。
  • 我认为 Stackoverflow 比 Embarcadero 的论坛更活跃、更激进。我在这里收到更多回复。
猜你喜欢
  • 2020-11-13
  • 2011-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多