Bonjour,

J'ajoute un ActiveX d'inter-opérabilité dans l'application !
Cet ActiveX doit être interchangeable, aujourd'hui, une application Delphi lance l'ActiveX qui pourra ouvrir un WebService SOAP ou REST, un Server TCP\IP ou que sais-je encore ?!

On souhaite ouvrir à l'extérieur (pour du PHP), un lot de fonction "noyau" de l'application, pour le moment, seules deux méthodes devraient être ouvertes !
Ces fonctions sont massives (et personne ne sait vraiment ce que cela fait)

Je ne serais plus dans la boite quand l'on utilisera cet objet en prod ! D'où l'idée saugrenue d'ouvrir ces fonctions à l'extérieur pour ne plus coder en Delphi certains modules mais en PHP

En fait, j'utilise le Système d'Evènement de la Couche COM comme dans le Tutoriel de Laurent Dardenne pour "rétro-implémenter" les deux fonctions magiques dans l'Application Delphi, pour que l'Active recevant une commande puisse appeler la fonction comme un event (avec paramètre bien sur)

Cela fonctionne plutôt bien sauf pour la remonter les erreurs HResult du SafeCall !
Ces erreurs ne remontent pas !!!
Dommage, moi qui gérait DISP_E_NONAMEDARGS, DISP_E_BADPARAMCOUNT, E_INVALIDARG... plus d'autre Exception Interne !

En fait, c'est plus un délire architecturel qu'autre chose ! Mais ça me fait plaisir !
Les Evènements, je ne les codes pas en dispinterface d'habitude, je fais mon propre Connect(EventIntf) et c'est plus facile, mais comme le système existe en standard autant l'essayer !

Voici ce que j'ai fait dans la partie Implementation de l'Objet COM (la DLL)
Je n'utilise pas le Gestionnaire d'evènement standard EventConnect hérité de TAutoObject, je rédéfini le mien HandlerConnectionPointEventConnect
C'est cool que cela soit ouvert !

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
type
  TCensureInterOp = class(TAutoObject, IConnectionPointContainer, ICensureIInterOp)
  private
    ...
    procedure HandlerConnectionPointEventConnect(const Sink: IUnknown; Connecting: Boolean); // C'est un Evènement passé directement dans Initialize
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
{* ----------------------------------------------------------------------------}
procedure TCensureInterOp.HandlerConnectionPointEventConnect(const Sink: IUnknown;
  Connecting: Boolean);
var
  varEventSink: IUnknown;
begin
  if Connecting then
  begin
    // Dézingage de TDispatchSilencer
    OleCheck(Sink.QueryInterface(AutoFactory.EventIID, varEventSink));
    EventSink := varEventSink;
    EventSinkChanged(EventSink);
  end
  else
  begin
    EventSink := nil;
    EventSinkChanged(nil);
  end;
end;
Noté de HandlerConnectionPointEventConnect à la place du EventConnect généré automatiquement lorsque l'on coche ‘Générer le code de support d'événement'
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
{* ----------------------------------------------------------------------------}
procedure TCensureInterOp.Initialize;
begin
  inherited Initialize;
  FConnectionPoints := TConnectionPoints.Create(Self);
  if AutoFactory.EventTypeInfo <> nil then
    FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
      AutoFactory.EventIID, ckSingle, HandlerConnectionPointEventConnect)
  else FConnectionPoint := nil;
end;
En retirant le TDispatchSilencer avec cette méthode, j'ai mes messages d'erreur via DISP_E_EXCEPTION dans ExcepInfo !
Au moins, je sais quand il y a une erreur !

C'est vilain ! non ?
Existe-t-il une méthode plus "simple" ?