Comment revenir WideString du serveur COM?
-
10-10-2019 - |
Question
Cette interface au fichier _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;
Cela ressemble à OS de 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);
};
Fonction de serveur dans les regards COM comme
function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin
Result := WideString(IntToStr(a+b));
end;
COM client i`m appeler cette fonction comme
Edit1.Text := String(MyCOM.MyDrawWS(1,1));
et obtenir erreur Première exception de chance $ 75A9FBAE. Exception classe EAccessViolation avec le message « Violation d'accès à l'adresse 75A409A4 dans le module 'rpcrt4.dll'. Lire d'adresse FFFFFFF8. Procédé Project1.exe (2296)
Si je veux retourner entier, il s `fonctionne. Comment revenir WideString?
La solution
La bonne façon de gérer est la suivante:
[
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;
Ce qui peut alors être simplifié un peu en utilisant la convention d'appel Delphi safecall
dans la déclaration Delphi (pas dans le TypeLibrary lui-même) de l'interface:
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);
Autres conseils
Ne pas utiliser des valeurs de retour autres que HRESULT. Au lieu de mettre votre valeur de retour dans la liste des paramètres en tant que paramètre de sortie.
function MyDrawWS(a: Integer; b: Integer; out str : WideString): HRESULT; stdcall;
De cette façon, vous êtes également obligé d'utiliser le gestionnaire de mémoire COM IMalloc (CoTaskMemAlloc pour COM pur, SysAllocString Automation).
Soit Delphi effectuer les conversions automatiquement. Ne pas jeter. Vous pouvez lancer une chaîne (ansi) à un PChar, parce que leur mise en page de mémoire sont compatibles, mais vous ne pouvez pas lancer une chaîne à un WideString ou vice-versa. Delphi conversion perfrom lorsque vous attribuez un à l'autre.
Dans Delphi <2009
var
S: string;
W: WideString;
...
S := W; // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString
Vous devez utiliser SysAllocString()
ou SysAllocStringLen()
d'affecter le BSTR
Première exception chance à $ 75A9FBAE. Exception classe EAccessViolation avec le message « Violation d'accès à l'adresse 75A409A4 dans le module 'rpcrt4.dll'
-
l'erreur provient de Rpcrt4.dll
-
EAccessViolation est principalement causée par l'accès à un objet null, étape par votre marque de code vous que tous les objets sont des objets valides.