Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2005.11.20;
Скачать: [xml.tar.bz2];

Вниз

Проблема с 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.043 c
14-1130249321
Hamertime
2005-10-25 18:08
2005.11.20
Расшифровка бинарного кода


3-1129003870
k2
2005-10-11 08:11
2005.11.20
Oracle9. ORA-03113


14-1130328203
Антоний
2005-10-26 16:03
2005.11.20
Удаленное администрирование локальной сети


2-1131216750
Groof
2005-11-05 21:52
2005.11.20
Помоги, люди добрые...


2-1130933037
~SaM~
2005-11-02 15:03
2005.11.20
Как сделать так, что бы окно программы было поверх ВСЕХ окон?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский