Wie Wide von COM-Server zurück?
-
10-10-2019 - |
Frage
Diese Schnittstelle bei _TLB.pas Datei
// *********************************************************************//
// 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;
Das sieht bei Betriebssystem 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);
};
Funktion in COM-Server aussieht wie
function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin
Result := WideString(IntToStr(a+b));
end;
In COM-Client i`m Aufruf dieser Funktion wie
Edit1.Text := String(MyCOM.MyDrawWS(1,1));
und erhalten Fehler Erste Chance Ausnahme bei $ 75A9FBAE. Ausnahmeklasse EAccessViolation mit der Meldung ‚Zugriffsverletzung bei Adresse 75A409A4 in Modul‚RPCRT4.dll‘. Lesen der Adresse FFFFFFF8' . Prozess Projekt1.exe (2296)
Wenn ich Integer will zurückkehren, es `s funktioniert. Wie zurückzukehren Wide?
Lösung
Der richtige Weg, dies zu handhaben ist wie folgt:
[
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;
Was dann ein wenig vereinfacht werden kann durch die Verwendung von Delphi safecall
Aufrufkonvention in der Delphi-Deklaration (in der Typbibliothek selbst) der Schnittstelle:
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);
Andere Tipps
Verwenden Sie Rückgabewerte nicht anders als HRESULT. setzen Sie Ihren Rückgabewert stattdessen in Parameterliste als Ausgangsparameter.
function MyDrawWS(a: Integer; b: Integer; out str : WideString): HRESULT; stdcall;
Auf diese Weise sind Sie auch zu verwenden COM-Speichermanager IMalloc (CoTaskMemAlloc für pur COM, SysAllocString für Automation) gezwungen.
Let Delphi führen Sie die Konvertierungen automatisch. Nicht werfen. Sie können eine (ANSI) Zeichenfolge in einen PChar umwandeln, weil ihr Gedächtnis Layout kompatibel sind, aber Sie können einen String in einem Wide oder umgekehrt nicht gegossen. Delphi wird perfrom Umwandlung, wenn Sie assign einem zum anderen.
In Delphi <2009
var
S: string;
W: WideString;
...
S := W; // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString
Sie müssen verwenden SysAllocString()
oder SysAllocStringLen()
die BSTR zuweisen
Erste Chance Ausnahme bei $ 75A9FBAE. Ausnahmeklasse EAccessViolation mit der Meldung ‚Zugriffsverletzung bei Adresse 75A409A4 in Modul‚RPCRT4.dll‘
-
der Fehler von RPCRT4.dll kommt
-
EAccessViolation wird hauptsächlich verursacht durch ein Null-Objekt zugreifen, Schritt für Schritt durch den Code stellen Sie sicher, alle Objekte sind gültige Objekte.