How to implement IOTAProjectCompileNotifier of Del

2019-02-15 15:35发布

I am using Delphi XE IDE. I create a notifier to implement IOTACompileNotifier. After install the expert in the IDE. The code works fine when I compile my project. The notifier is working for ProjectCompileStarted.

The second time I compile my project, the Delphi IDE prompt:

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

Although it seems weird that I perform:

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

in notifier. I just want to show Add and Remove compile notifier for ProjectBuilder seems not functioning properly no matter how I use.

Please advise how should I implement IOTAProjectCompileNotifier.

Thank you.

Here are the full source code:

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.

3条回答
我只想做你的唯一
2楼-- · 2019-02-15 15:49

error code "Read of address 00000000" can indicate that you are trying to access a resource which does not exist. I saw that you've asked the same question on the Embarcadero forum. From what I saw on here on SO, there are only several developers who are interested on OTA, the documentation from CG or Embarcadero is almost inexistent, so I'm suggesting you to insist on Embarcadero's forum.

best regards,
Radu

查看更多
老娘就宠你
3楼-- · 2019-02-15 15:55

I think I might be able to answer this. I don't have XE and so I don't appear to have IOTAProjectCompileNotifier. However, the other AddNotifier methods in my ToolsAPI unit suggest it will be declared as:

function AddNotifier(const ANotifier: IOTAProjectCompileNotifier): Integer;

You call this routine this way:

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

The problem is that nothing takes a reference to the interface returned by TProjectCompileNotifier.Create. You need to do so, like this:

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;

You'd need to do likewise in the initialization/finalization code.

I believe that this really should be considered a bug in the interface reference counting implementation. It has been discussed here on Stack Overflow many times.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-02-15 15:59

I wonder why you're removing your notifier from within the callback. I could imagine that scenario is not handled well by OTA. Try the following: first (when the package is loaded and initialized) install an IOTAIDENotifier to be notified when a project is open (remove it in finalization). Implement its FileNotification to add your IOTAProjectCompileNotifier when a project is open, remove it when it's closed.

查看更多
登录 后发表回答