Рассмотрим проблему, с которой сталкиваются разработчики, работающие с COM-серверами в среде Delphi: корректный возврат значений типа WideString. Проблема заключается в том, что при попытке возврата строки из COM-сервера в клиентскую программу возникает ошибка доступа. Это происходит из-за особенностей работы с памятью в COM и необходимости использования специальных функций для работы со строками.
Описание проблемы
В интерфейсе ITMyCOM, определенном в файле _TLB.pas, функция MyDrawWS должна возвращать значение типа WideString. Однако при попытке вызвать эту функцию в клиентской программе возникает исключение доступа (EAccessViolation), указывающее на ошибку при работе с памятью.
Решение проблемы
Для корректного возврата строк WideString из COM-сервера необходимо использовать функции SysAllocString() или SysAllocStringLen(), которые отвечают за выделение памяти для строк типа BSTR. В Delphi также возможно использовать тип WideString, и среда выполнит все необходимые операции выделения памяти автоматически.
Однако, согласно стандартам COM, функции должны возвращать только значение типа HRESULT, а возвращаемые значения должны передаваться через параметры, отмеченные как out. В этом случае для работы со строками следует использовать функции, такие как CoTaskMemAlloc для чистого COM или SysAllocString для автоматизации.
Пример корректного использования
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;
В клиентской программе для получения результата следует использовать OleCheck, чтобы проверить успешность выполнения функции:
var
W: WideString;
begin
OleCheck(MyCOM.MyDrawWS(1, 1, W));
Edit1.Text := W;
end;
Также можно упростить код, используя соглашение вызовов safecall в Delphi для работы с функциями COM:
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);
При использовании safecall Delphi автоматически обработает возвращаемое значение и параметры, что упрощает работу с COM-интерфейсами.
Заключение
Для корректного возврата строк из COM-сервера в Delphi необходимо использовать функции для работы с памятью и строками, предоставляемые COM, или же позволить среде выполнить все необходимые операции автоматически. Следуя этим рекомендациям, можно избежать ошибок доступа и обеспечить правильную работу с COM-объектами.
Проблема заключается в необходимости корректного возврата строк типа `WideString` из COM-сервера в Delphi, что требует использования специальных функций для работы с памятью и строками в соответствии со стандартами COM.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.