Здравствуйте. Есть проблема: не удается поднимать событие в COM. Далее подробнее:
1. Запускаю приложение App1, создаю в нем COM-объект, вешаюсь на событие внутренним обработчиком:
unit TestUnit;
interface
uses
PYCE_TLB;
type
TTestForm = class(TForm)
TestButton: TButton;
LabelI: TLabel;
LabelL: TLabel;
Labelid: TLabel;
procedure TestButtonClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
public
procedure NextIter(Sender: TObject; I, L, id: Integer);
end;
var
TestForm: TTestForm;
MyObj: TYCE;
procedure DLL_proc1 (...); cdecl; external('DLL');
implementation
procedure TTestForm.NextIter(Sender: TObject; I, L, id: Integer);
begin
LabelI.Caption := IntToStr(I);
LabelL.Caption := IntToStr(L);
Labelid.Caption := IntToStr(id);
Application.ProcessMessages;
end;
procedure TTestForm.TestButtonClick(Sender: TObject);
var id, P: Integer;
begin
try
MyObj := TYCE.Create(self);
MyObj.Connect;
MyObj.OnENext := NextIter;
id := MyObj.RegId;
MyObj.GNextIter(P*25,P*35,1);
DLL_proc1(id);
except
LabelI.Caption := '-1';
end;
end;
procedure TTestForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if MyObj <> nil then
MyObj.Disconnect;
end;
end.
MyObj: TYCE;
2. Внутри приложения App1, как вы заметили, вызываю proc1 из DLL(написана на Matlab-е).
3. Внутри proc1 тоже вызываю COM-объект типа TYCE:
код на Matlab-е
e = actxserver ('PYCE.YCE');
for i=1:100
e.Next(i,i*10,1);
end
4. Как видите, Matlab-овский код сто раз вызывает метод, который генерит событие ENext с тремя параметрами.
5. Теперь, собственно, описание COM-а:
unit YCEUnit;
interface
uses
PYCE_TLB;
type
TYCE = class(TAutoObject, IConnectionPointContainer, IYCE)
private
FConnectionPoints: TConnectionPoints;
FConnectionPoint: TConnectionPoint;
FEvents: IYCEEvents;
public
procedure Initialize; override;
protected
property ConnectionPoints: TConnectionPoints read FConnectionPoints
implements IConnectionPointContainer;
procedure EventSinkChanged(const EventSink: IUnknown); override;
function RegId: Integer; safecall;
procedure Next(I, L, id: Integer); safecall;
end;
implementation
uses ComServ, MainUnit;
procedure TYCE.EventSinkChanged(const EventSink: IUnknown);
begin
COMForm.FEvent := FEvents;
FEvents := EventSink as IYCEEvents;
COMForm.FEvent := FEvents;
end;
procedure TYCE.Initialize;
begin
inherited Initialize;
FConnectionPoints := TConnectionPoints.Create(Self);
if AutoFactory.EventTypeInfo <> nil then
FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
AutoFactory.EventIID, ckSingle, EventConnect)
else FConnectionPoint := nil;
end;
function TYCE.RegId: Integer;
begin
COMForm.ListOfId.Add(COMForm.FEvent);
COMForm.idCount := COMForm.idCount+1;
Result := COMForm.idCount-1;
end;
procedure TYCE.Next(I, L, id: Integer);
var
MyFEvent: IYCEEvents;
begin
COMForm.LabelI.Caption := IntToStr(I)+' '+IntToStr(L)
+' '+IntToStr(id);
Application.ProcessMessages;
MyFEvent := IYCEEvents(COMForm.ListOfId.Items[0]);
MyFEvent.ENext(I, L, id);
end;
initialization
TAutoObjectFactory.Create(ComServer, TYCE, Class_YCE,
ciMultiInstance, tmApartment);
end.
6. Итак, когда иду в режиме отладчика получаю следующую картину:
Matlab-овская Dll-ка заходит в метод Next, на label-ах COMForm-ы появляется подтверждение этому. Из листа достается MyFEvent (тот же, что и при вызове метода Next из App1(=> COMForm и для App1 и для DLL одна общая)), а вот на следующей строчке:
MyFEvent.ENext(I, L, id);
все зависает. Никакого события не генериться.
Понимаю, что краткость-сестра таланта, но хотелось более полно описать сложившуюся ситуацию.
Заранее спасибо за помощь в решении данного вопроса.