Главная страница
    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.038 c
3-1128921953
Layner
2005-10-10 09:25
2005.11.20
Через ADO не работает SQL запрос в Access, из Access нормально..


2-1130762140
Fast2
2005-10-31 15:35
2005.11.20
Как, во время выполнения приги, узнать колличество и имена полей


1-1130499343
Шурик Ш
2005-10-28 15:35
2005.11.20
Вопрос про события TValueListEditor


1-1130676546
Draught
2005-10-30 15:49
2005.11.20
Замена Memo на что либо более подходящее


3-1128587582
Maverick
2005-10-06 12:33
2005.11.20
Выполнение скриптов в MSSQL





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский