Как вернуть WideString с COM-сервера? - PullRequest
2 голосов
/ 15 ноября 2010

Этот интерфейс в файле _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;

Это выглядит на ОС 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);
};

Функция на COM-сервере выглядит как

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

В COM-клиенте я вызываю эту функцию как

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

и получите ошибку Первое исключение на уровне $ 75A9FBAE. Класс исключения EAccessViolation с сообщением «Нарушение прав доступа по адресу 75A409A4 в модуле« RPCRT4.dll ». Прочитайте адрес FFFFFFF8 '. Процесс Project1.exe (2296)

Если я хочу вернуть Integer, это работает. Как вернуть WideString?

Ответы [ 5 ]

1 голос
/ 18 ноября 2010

Правильный способ справиться с этим заключается в следующем:

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

, который затем можно немного упростить, используя safecall соглашение о вызовах Delphi в объявлении Delphi (не в самой TypeLibrary)интерфейс:

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);
1 голос
/ 15 ноября 2010

Не используйте возвращаемые значения, кроме HRESULT.Вместо этого поместите возвращаемое значение в список параметров в качестве выходного параметра.

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

Таким образом, вы также будете вынуждены использовать диспетчер памяти COM IMalloc (CoTaskMemAlloc для pur COM, SysAllocString для автоматизации).

1 голос
/ 15 ноября 2010

Позвольте Delphi выполнить преобразования автоматически.Не бросай.Вы можете привести (ansi) строку к PChar, потому что их расположение в памяти совместимо, но вы не можете привести строку к самой широкой строке или наоборот.Delphi выполнит преобразование, когда вы назначите одно другому.

В Delphi <2009 </p>

var
S: string;
W: WideString;
...
S := W;  // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString
0 голосов
/ 16 ноября 2010

Исключение первого шанса на $ 75A9FBAE.Класс исключений EAccessViolation с сообщением «Нарушение доступа по адресу 75A409A4 в модуле« RPCRT4.dll »

  1. ошибка поступает из RPCRT4.dll

  2. EAccessViolation в основном вызывается доступом к нулевому объекту, следуя по коду, убедитесь, что все объекты являются допустимыми объектами.

0 голосов
/ 15 ноября 2010

Вам необходимо использовать SysAllocString() или SysAllocStringLen() для выделения BSTR.

...