开发者

How to return WideString from COM server?

This Interface at _TLB.pas file

// *********************************************************************//
// 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;

This looks at OS 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);
};

Function in COM server looks as

function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin
Result := WideString(IntToStr(a+b));
end;

In COM Client i`m calling this function like

Edit1.Text := String(MyCOM.MyDrawWS(1,1));

and get error First chance exception at $75A9FBAE. Exception class EAccessViolatio开发者_如何学Gon with message 'Access violation at address 75A409A4 in module 'RPCRT4.dll'. Read of address FFFFFFF8'. Process Project1.exe (2296)

If i want returning Integer, it`s works. How to return WideString?


The correct way to handle this is as follows:

[ 
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;

Which can then be simplified a little by using Delphi's safecall calling convention in the Delphi declaration (not in the TypeLibrary itself) of the 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);


Let Delphi perform the conversions automatically. Don't cast. You can cast a (ansi)string to a PChar, because their memory layout are compatible, but you can't cast a string to a widestring or viceversa. Delphi will perfrom conversion when you assign one to the other.

In Delphi < 2009

var
S: string;
W: WideString;
...
S := W;  // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString


Don't use return values other than HRESULT. Instead put your return value into parameter list as output parameter.

function MyDrawWS(a: Integer; b: Integer; out str : WideString): HRESULT; stdcall;

In this way, you are also forced to use COM memory manager IMalloc (CoTaskMemAlloc for pur COM, SysAllocString for Automation).


You need to use SysAllocString() or SysAllocStringLen() to allocate the BSTR.


First chance exception at $75A9FBAE. Exception class EAccessViolation with message 'Access violation at address 75A409A4 in module 'RPCRT4.dll'

  1. the error is coming from RPCRT4.dll

  2. EAccessViolation is mostly caused by accessing a null object, step through your code make sure all objects are valid objects.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜