Environment is Delphi XE2 Enterprise.
Relates to use dispInterface in Delphi with no classid. Re-posting as a different question as I have moved well beyond the previous issues (thanks to @EricBrown) and now have a more specific problem.
I've got a .NET dll with a COM interface that I've registered on the computer and have imported as a type library into Delphi. I'm using the tlb.pas file that Delphi created.
Working with a couple of dispInterfaces that I've implemented in IDispatch interfaces and TAutoIntf descendant classes, I've successfully initialized the classes and interfaces that I need to call methods in the COM interface to the .NET library. Here is some code to illustrate the declaration/implementation:
// COM Event Sink GUID
DIID_IResponseListener: TGUID = '{ABC29F08-B628-4747-BA9E-469D408E57B9}';
// *********************************************************************//
// DispIntf: IResponseListener
// Flags: (4096) Dispatchable
// GUID: {ABC29F08-B628-4747-BA9E-469D408E57B9}
// *********************************************************************//
IResponseListener = dispinterface
['{ABC29F08-B628-4747-BA9E-469D408E57B9}']
procedure RequestCompleted(const requestID: WideString; const responseObj: IResponse); dispid 1610744833;
procedure RequestFailed(const requestID: WideString; const error: WideString); dispid 1610744834;
procedure TablesUpdates(const responseObj: IResponse); dispid 1610744835;
end;
...my implementation:
IFXResponseListener = interface(IDispatch)
['{3204D3F7-5DF2-4470-89D5-D34F4F6F0381}']
procedure RequestCompleted(const requestID: WideString; const responseObj: IResponse); dispid 1610744833; safecall;
procedure RequestFailed(const requestID: WideString; const error: WideString); dispid 1610744834; safecall;
procedure TablesUpdates(const responseObj: IResponse); dispid 1610744835; safecall;
end;
TFXResponseListener = class(TAutoIntfObject,IFXResponseListener)
private
FDisp: IDispatch;
FResp: IResponse;
function GetResponseListIntf: IResponseListener;
public
constructor Create;
destructor Destroy;
published
procedure RequestCompleted(const requestID: WideString; const responseObj: IResponse); safecall;
procedure RequestFailed(const requestID: WideString; const error: WideString); safecall;
procedure TablesUpdates(const responseObj: IResponse); safecall;
property ResponseObj: IResponse read FResp;
property ListenerDispIntf: IResponseListener read GetResponseListIntf;
end;
...
{ TFXResponseListener }
constructor TFXResponseListener.Create;
var
TypeLib: ITypeLib;
begin
OleCheck(LoadRegTypeLib(LIBID_fxcore2_com,fxcore2_comMajorVersion,fxcore2_comMinorVersion,0,TypeLib));
inherited Create(TypeLib,DIID_IResponseListener);
end;
destructor TFXResponseListener.Destroy;
begin
inherited;
end;
function TFXResponseListener.GetResponseListIntf: IResponseListener;
begin
FDisp := Self as IFXResponseListener;
FDisp._AddRef;
Result := IResponseListener(FDisp);
end;
procedure TFXResponseListener.RequestCompleted(const requestID: WideString; const responseObj: IResponse);
begin
showmessage('Completed: ' + requestID);
FResp := responseObj;
end;
procedure TFXResponseListener.RequestFailed(const requestID: WideString; const error: WideString);
begin
showmessage('Failed: ' + requestID);
end;
procedure TFXResponseListener.TablesUpdates(const responseObj: IResponse);
begin
showmessage('TablesUpdates');
end;
Here is where I attempt to use the interface:
FRespList := TFXResponseListener.Create;
try
FSess.subscribeResponse(FRespList.ListenerDispIntf);
except
// errors out here with 'The parameter is incorrect'
end;
Tracing this down into the bowels of System.Win.ComObj, at line 1793 it calls:
Status := Dispatch.Invoke(DispID, GUID_NULL, 0, InvKind, DispParams, Result, @ExcepInfo, nil);
At this point, the DispID parameter is valid (1610743816), GUID_NULL is '(0, 0, 0, (0, 0, 0, 0, 0, 0, 0, 0))', InvKind is '1', DispParams is '($2152FE8, nil, 1, 0)', Result is '$12FE24', @ExcepInfo is '$12FDE0'.
In System.pas, line 30133, TInterfacedObject.QueryInterface is called twice. On the second run it returns the result 'E_NOINTERFACE', and the dreaded 'The parameter is incorrect' message appears.
I'm really not sure where to go from here, but I'm hoping a COM expert and/or Delphi expert can review this and see something amiss.
I'm also wondering if there is a .NET framework version or other issue. I'm using framework version 4.5.1; not sure how to determine if the .NET assembly is kosher with this version of the framework or if it really needs an earlier version.
Any relevant .NET/COM debugging techniques would be greatly appreciated.
Also please note, I can duplicate this issue with a different dispinterface/IDispatch/TAutoIntfObj descendant class and similar call, identical to a 'T'.
Thanks.