Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.11.20;
Скачать: CL | DM;

Вниз

Проблема с idHTTP   Найти похожие ветки 

 
DVladimir   (2005-08-03 03:15) [0]

Приветствую!

Возникла странная проблема:
взял кусок кода из модуля idHTTP, вставил в свою библиотеку - а он не работает. Кусок наипростейший, но тем не менее.

Чтобы было всё предельно понятно, привожу вызов неработающей функции и библиотеку, в которой функция описана:

--Вызов: ---

Var Content, buf: PChar;
TestProc: function: PChar;
DLLHandle: THandle;
......
 DLLHandle:=LoadLibrary("libTest");
 if(DLLHandle = 0) then Begin
   ShowMessage("Cannot load DDL");
   Application.Terminate;
 end;
 try
   @TestProc:=GetProcAddress(DLLHandle,PChar("GetURL"));
   try
     buf:=TestProc;
     //Предполагаю, что buf не nil (так оно есть) - проверку опущу
     GetMem(Content, Length(buf)+1);
     Content:=StrLCopy(Content,buf,Length(buf));
     ShowMessage(StrPas(Content));
   except
     ShowMessage("Error in GetURL"); //Вот эта ошибка вылетает
     Application.Terminate;
   end;
 finally
   FreeLibrary(DLLHandle);
 end;

--Библиотека: ---

library libTest;

uses
 SysUtils,
 Classes,
 Dialogs, //Just for ShowMessage()
 idHTTP;

{$R *.res}

function GetURL: PChar;
Var
 HTTP: TidHTTP;
 strResponse: TMemoryStream;
 b: String;
Begin
 HTTP:=TidHTTP.Create(nil);
 HTTP.Host:="localhost";
 HTTP.Port:=80;
 strResponse:=TMemoryStream.Create;
 {$H+} //For ANSI string...
 try
   HTTP.Connect(-1);
   HTTP.DoRequest(hmGet, "http://localhost/test.html", nil, strResponse);
   if strResponse.Size > 0 then begin
     ShowMessage("Readed: "+IntToStr(a));
     try
       SetLength(b,strResponse.Size); //Вот тут если руками прописать около 1000 байт, ошибки не бывает
       Move(PChar(strResponse.Memory)^, b[1],strResponse.Size);
     except
       //Ни одно из перечисленных exception-ов не возникает.
       //Вернее блок exception вообще не выполняется
       on E: EOutOfMemory do ShowMessage("E: "+E.Message);
       on E: EInvalidPointer do ShowMessage("E: "+E.Message);
       on E: EAccessViolation do ShowMessage("E: "+E.Message)
       else ShowMessage("Unknown error");
     end;
   end;
   Result:=PChar(b);
 except
   Result:=PChar("Error: "+IntToStr(HTTP.ResponseCode));
 end;
 strResponse.Free;
 HTTP.Disconnect;
 HTTP.Destroy;
end;

exports
 GetURL;

begin
end.

Помогите найти ошибку!
Спасибо!


 
Lamer@fools.ua ©   (2005-08-03 07:16) [1]

> Result:=PChar(b);

Это неправильно. После выхода из функции указатель станет невалидным.


 
DVladimir   (2005-08-03 13:08) [2]

Да нет.
Т.е. если я пишу
SetLength(b,500); //Вот тут если руками прописать около 1000 байт, ошибки не бывает
Move(PChar(strResponse.Memory)^, b[1],500);

То вызывающая функция получает указатель на 500 байт полученного текста. И вот это
GetMem(Content, Length(buf)+1);
Content:=StrLCopy(Content,buf,Length(buf));
ShowMessage(StrPas(Content));

прекрасно отрабатывает.


 
Digitman ©   (2005-08-03 13:21) [3]


> DVladimir   (03.08.05 13:08) [2]
> Да нет.


да ДА !!

причем здесь "около 1000 байт" ?

время жизни лок.переменной процедуры равно времени жизни процедуры !


 
Slym ©   (2005-08-03 14:30) [4]

function GetURL(Buf:PChar;SizeBuf:integer): LongBool;
Var
 Response: TMemoryStream;
 HTTP: TidHTTP;
Begin
 try
   Response:=TMemoryStream.Create;
   try
     HTTP:=TidHTTP.Create(nil);
     try
       HTTP.Get("http://localhost/test.html", Response);
       if Response.Size>0 then
       begin
         ShowMessage("Readed: "+IntToStr(Response.Size));
         StrLCopy(Buf,Response.Memory,SizeBuf-1);
       end else
       if SizeBuf>0 then
       Buf^:=#0;
     finally
       HTTP.Free;
     end;
   finally
     Response.Free;
   end;
   result:=true;
 except
   on E:Exception do
   begin
     result:=false;
     StrLCopy(Buf,PChar(Format("Raised exception %s with message %s",[E.ClassName,E.Message])),SizeBuf-1);
   end;
 end;
end;


TestProc:=GetProcAddress(DLLHandle,PChar("GetURL"));
GetMem(Content, 1024);
try
 TestProc(Content, 1024);
 ShowMessage(StrPas(Content));
finally
 FreeMem(Content);
end;


 
DVladimir   (2005-08-03 17:09) [5]

Digitman ©   (03.08.05 13:21) [3]

Это-то да.
Не могу спорить, т.к. понимаю, что скорее всего не прав.
Скажу лишь в оправдание, что мне привычнее такое поведение:

sub MyProc {
 my $a = "Some data";
 return \$a;
}

и после вызова
my $ref_a = MyProc();

я получу не мертвый указатель, а именно указатель на "Some data";

Это на самом деле мой чуть ли не первый опыт на Delphi.
Тем не мнее спасибо большое!


 
DVladimir   (2005-08-03 17:44) [6]

Slym ©   (03.08.05 14:30) [4]

Да, всё четко и понятно.
Спасибо большое!

Только вопрос несколько уже офф-топик.
Имеет ли смысл вызов    
Response:=TMemoryStream.Create;
оборачивать в try ... except ?
Ну в смысле я не знаю какие могут исключения возникнуть...


 
Digitman ©   (2005-08-04 08:38) [7]


> мне привычнее такое поведение


не путай.
это совсем другой случай.


> Имеет ли смысл вызов    
> Response:=TMemoryStream.Create;
> оборачивать в try ... except ?


исключение при конструировании этого объекта весьма маловероятно.
например, может возникнуть EOutOfMemory, если на этот момент ты опустошил кучу


 
Slym ©   (2005-08-04 09:06) [8]

Для новичков ВСЕГДА имеет смысл.
Это "ручной" SafeCall - ДЛЛ должна сама обработать все ошибки! и в лучшем случае вернуть true/false в худшем код ошибки для дальнейшего анализа в программе


 
DVladimir   (2005-08-04 16:35) [9]

Ага, почти всё понял. Спасибо!

Возникла еще проблема :) Прошу извинения, если достал.

Я решил в функцию не передавать BufSize, т.к. реально его размер я не знаю до получения страницы. Сделал так:


   try
    HTTP:=TidHTTP.Create(nil);
    try
      HTTP.Get("http://localhost/test.html", Response);
      if Response.Size>0 then
      begin
        ShowMessage("Readed: "+IntToStr(Response.Size));
        GetMem(Buf,Response.Size); //+1 ли?
        StrLCopy(Buf,Response.Memory,Response.Size-1);
      end else
      Buf^:=#0;
    finally
      HTTP.Free;
    end;
  finally
    Response.Free;
  end;


И после GetMem у меня размер Buf становится = 3, а после StrLCopy в нем какие-то странные 3 байта.

Я даже попробовал в этой функции объявить локальную
test: PChar, так и после
GetMem(test,Response.Size);
обнаруживаю, что Length(test) равно 3.

Что я опять не так делаю, в чем не прав?
Спасибо!


 
Slym ©   (2005-08-04 17:04) [10]

обнаруживаю, что Length(test) равно 3.
Мдя... Ацес Виолатион по тебе плачет...

GetMem(Buf,Response.Size+1); //+1 ли? - Именно!

с PChar так "Length(test)" не поступают



Страницы: 1 вся ветка

Текущий архив: 2005.11.20;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.044 c
14-1130242397
Opilki_Inside
2005-10-25 16:13
2005.11.20
Some problems using Copy & Paste with different browsers


14-1130740490
pavel_guzhanov
2005-10-31 09:34
2005.11.20
Книга Марко Кэнту


2-1131018738
Woolen
2005-11-03 14:52
2005.11.20
Непонятное поведение строк


2-1128177159
Giga
2005-10-01 18:32
2005.11.20
SMTP сервер


3-1121670907
АМБ
2005-07-18 11:15
2005.11.20
Просмотр и восстановление "удаленных" записей в DBF таблицах