Получение IStream из OleVariant

Я использую Delphi вместе с WinHTTP для выполнения HTTP-запроса для загрузки некоторых файлов из Интернета, и я могу выполнить запрос, но я не знаю, как получить IStream из OleVariant, который возвращается из ResponseStream. Я потратил много времени на поиск в Google, но не могу понять, как это сделать. Вот что я пробовал:

var
  req: IWinHTTPRequest;
  instream: IStream;
begin
  req := CoWinHTTPRequest.Create;

  req.Open('GET', 'http://google.com', false);
  req.Send('');

  if req.Status <> 200 then
  begin
    ShowMessage('failure'#10 + req.StatusText);

    FreeAndNil(req);

    Application.Terminate;
  end;

  instream := req.ResponseStream as IStream;

  ShowMessage('success');

  FreeAndNil(instream);
  FreeAndNil(req);

end;

Но я получаю сообщение об ошибке [DCC Error] main.pas(45): E2015 Operator not applicable to this operand type (строка 45 - instream := req.ResponseStream as IStream;).

Как мне напугать IStream до OleVariant?


person Okey    schedule 08.02.2011    source источник
comment
Ваше предположение о том, что выполнение останавливается при вызове Application.Terminate, неверно. Это просто отправит WM_QUIT сообщение, но ваша функция продолжит выполнение.   -  person David Heffernan    schedule 09.02.2011


Ответы (1)


Попробуй это

instream := IUnknown(req.ResponseStream) as IStream;

Изменить 1. Вы не должны вызывать FreeAndNil в интерфейсе. FreeAndNil можно передать только экземпляр объекта. В противном случае возникает исключение. Поскольку интерфейсы в любом случае подсчитываются по ссылкам, вы можете просто отпустить их из области видимости, и они будут очищены. Итак, вам необходимо удалить:

  FreeAndNil(instream);
  FreeAndNil(req);

Edit2: попробуйте объяснить, что происходит

Пожалуйста, не стесняйтесь редактировать или дополнять, если вы считаете, что это неточно или если это можно объяснить лучше.

req.ResponseStream - это OleVariant. Ключевое слово as выполняет вызов QueryInterface, и это не реализовано в OleVariant.

OleVariant имеет встроенное преобразование типа из OleVariant в IUnknown, поэтому вам нужно сначала преобразовать OleVariant в IUnknown, а затем использовать оператор as, чтобы выполнить QueryInterface, чтобы получить интерфейс IStream.

Вы не можете преобразовать OleVariant напрямую в IStream, потому что нет встроенного преобразования типа из OleVariant в IStream.

person Mikael Eriksson    schedule 08.02.2011
comment
Дело не столько в том, что вы должны делать это с чем-то, что подсчитывается по ссылкам, сколько в том, что они не являются подклассами TObject, и поэтому называть их Free бессмысленно. - person David Heffernan; 09.02.2011
comment
@ Дэвид Хеффернан - вы получаете нарушение прав доступа, когда процедура выходит за рамки, если вы это делаете. Я предполагаю, что это вызвано вызовом Release после завершения процедуры. - person Mikael Eriksson; 09.02.2011
comment
@Mikael Вы не можете вызвать Free через интерфейс. Вы можете вызывать Free только для объекта. Подсчет ссылок не имеет значения. Единственный способ обойтись с FreeAndNil - это использовать нетипизированный параметр. Удаление части, которая не содержит ссылки, это procedure FreeAndNil(var obj); begin TObject(obj).Free; end; - person David Heffernan; 09.02.2011
comment
@David - Вы можете создать свой собственный код, импортировав библиотеку типов для Microsoft WinHTTP Services. - person Mikael Eriksson; 09.02.2011
comment
@Mikael Я отредактировал твою правку! Думаю, теперь стало понятнее. Я действительно не понимаю, что происходит, потому что IWinHTTPRequest.ResponseStream - это IStream согласно MSDN. - person David Heffernan; 09.02.2011
comment
@Mikael Спасибо, я пытался понять, какая это была библиотека типов! - person David Heffernan; 09.02.2011
comment
@Mikael property ResponseStream: OleVariant Странно! MSDN сообщает, что это вариант A, который получает указатель на интерфейс IUnknown, который можно запросить для интерфейса IStream. Для меня это слишком сложно !! - person David Heffernan; 09.02.2011
comment
@David Здесь описывается метод получения интерфейса из OleVariant. techvanguards.com/stepbystep/comdelphi/client.asp. Примерно на 2/3 ниже в документе. Кое-что об извлечении указателя на интерфейс vtable. Слишком поздно для меня понять, почему это нужно делать именно так. - person Mikael Eriksson; 09.02.2011
comment
@mikael спасибо. Ваш ответ будет улучшен с объяснением трюка и этой ссылки. Как это кажется немного волшебным! В любом случае, хорошая работа, и я снова узнаю здесь что-то новое! - person David Heffernan; 09.02.2011
comment
@David - Пытался объяснить в ответ, что происходит и почему нужно преобразовать в IUnknown перед использованием as IStream. Я не могу объяснить внутреннюю работу OleVariant и то, как работает неявное преобразование типов для OleVariant. - person Mikael Eriksson; 09.02.2011
comment
@Mikael Я думаю, что потрачу немного времени, пытаясь понять эту идиому, и если да, то я, возможно, отредактирую ваш ответ дальше. Было бы неплохо запечатлеть этот трюк где-нибудь, и он может присутствовать в другом ответе на другой Q уже здесь. - person David Heffernan; 09.02.2011
comment
@Mikael Я обдумывал это, читал об этом, и я думаю, что ваша последняя редакция довольно хорошо передает сообщение. - person David Heffernan; 10.02.2011