Come restituire WideString dal server COM?
-
10-10-2019 - |
Domanda
Questa interfaccia a file di _TLB.pas
// *********************************************************************//
// Interface: ITMyCOM
// Flags: (256) OleAutomation
// GUID: {D94769D0-F4AF-41E9-9111-4D8BC2F42D69}
// *********************************************************************//
ITMyCOM = interface(IUnknown)
['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}']
function MyDrawWS(a: Integer; b: Integer): WideString; stdcall;
end;
Questa guarda operativo Windows
[
odl,
uuid(D94769D0-F4AF-41E9-9111-4D8BC2F42D69),
version(1.0),
helpstring("Interface for TMyCOM Object"),
oleautomation
]
interface ITMyCOM : IUnknown {
BSTR _stdcall MyDrawWS(
[in] long a,
[in] long b);
};
Funzione nel look server COM come
function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin
Result := WideString(IntToStr(a+b));
end;
`m In COM client di chiamare questa funzione come
Edit1.Text := String(MyCOM.MyDrawWS(1,1));
e ottenere l'errore eccezione Prima possibilità a $ 75A9FBAE. Eccezione di classe EAccessViolation con 'Violazione di accesso all'indirizzo 75A409A4 nel modulo 'messaggio rpcrt4.dll'. Leggi di indirizzo FFFFFFF8' . Processo Progetto1.exe (2296)
Se voglio tornare Integer, `s funziona. Come restituire WideString?
Soluzione
Il modo corretto per gestire questa situazione è la seguente:
[
odl,
uuid(D94769D0-F4AF-41E9-9111-4D8BC2F42D69),
version(1.0),
helpstring("Interface for TMyCOM Object"),
oleautomation
]
interface ITMyCOM : IUnknown {
HRESULT _stdcall MyDrawWS(
[in] long a,
[in] long b,
[out, retval] BSTR* ret);
};
ITMyCOM = interface(IUnknown)
['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}']
function MyDrawWS(a: Integer; b: Integer; out ret: WideString): HResult; stdcall;
end;
function TTMyCOM.MyDrawWS(a, b: Integer; out ret: WideString): HRESULT;
begin
ret := IntToStr(a+b);
Result := S_OK;
end;
var
W: WideString;
begin
OleCheck(MyCOM.MyDrawWS(1, 1, W));
Edit1.Text := W;
end;
che possono poi essere semplificato un po 'utilizzando safecall
convenzione di chiamata di Delphi nella dichiarazione Delphi (non nel TypeLibrary stesso) dell'interfaccia:
ITMyCOM = interface(IUnknown)
['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}']
function MyDrawWS(a: Integer; b: Integer): WideString; safecall;
end;
function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin
Result := IntToStr(a+b);
end;
Edit1.Text := MyCOM.MyDrawWS(1, 1);
Altri suggerimenti
Non utilizzare i valori restituiti diversi HRESULT. Invece mettere il valore di ritorno nella lista dei parametri come parametro di uscita.
function MyDrawWS(a: Integer; b: Integer; out str : WideString): HRESULT; stdcall;
In questo modo, si è costretti anche ad uso COM gestore di memoria IMalloc (CoTaskMemAlloc per PUR COM, SysAllocString per l'Automazione).
Let Delphi eseguire automaticamente le conversioni. Non pressofuso. Si può lanciare una stringa (ANSI) per un PChar, perché il loro layout di memoria sono compatibili, ma non è possibile lanciare una stringa in un WideString o viceversa. Delphi perfrom conversione quando un assegnare all'altro.
In Delphi <2009
var
S: string;
W: WideString;
...
S := W; // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString
È necessario utilizzare SysAllocString()
o SysAllocStringLen()
di destinare l'BSTR
Per prima eccezione di possibilità a $ 75A9FBAE. classe di eccezione EAccessViolation con il messaggio 'Violazione di accesso all'indirizzo 75A409A4 nel modulo 'rpcrt4.dll'
-
l'errore viene da rpcrt4.dll
-
EAccessViolation è in gran parte causato da l'accesso a un oggetto null, passo attraverso il codice di assicurarsi che tutti gli oggetti sono oggetti validi.