![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с idHTTP [D7, WinXP]
DVladimir © (2005-08-03 03:15:00)Приветствую!
Возникла странная проблема:
взял кусок кода из модуля 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.
Помогите найти ошибку!
Спасибо!
Slym (2005-08-04 17:04:00) [1]обнаруживаю, что Length(test) равно 3.
Мдя... Ацес Виолатион по тебе плачет...
GetMem(Buf,Response.Size+1); //+1 ли? - Именно!
с PChar так "Length(test)" не поступают
DVladimir (2005-08-04 16:35:00) [2]Ага, почти всё понял. Спасибо!
Возникла еще проблема :) Прошу извинения, если достал.
Я решил в функцию не передавать 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 09:06:00) [3]Для новичков ВСЕГДА имеет смысл.
Это "ручной" SafeCall - ДЛЛ должна сама обработать все ошибки! и в лучшем случае вернуть true/false в худшем код ошибки для дальнейшего анализа в программе
Digitman (2005-08-04 08:38:00) [4]
> мне привычнее такое поведение
не путай.
это совсем другой случай.
> Имеет ли смысл вызов
> Response:=TMemoryStream.Create;
> оборачивать в try ... except ?
исключение при конструировании этого объекта весьма маловероятно.
например, может возникнуть EOutOfMemory, если на этот момент ты опустошил кучу
DVladimir (2005-08-03 17:44:00) [5]Slym © (03.08.05 14:30) [4]
Да, всё четко и понятно.
Спасибо большое!
Только вопрос несколько уже офф-топик.
Имеет ли смысл вызов
Response:=TMemoryStream.Create;
оборачивать в try ... except ?
Ну в смысле я не знаю какие могут исключения возникнуть...
DVladimir (2005-08-03 17:09:00) [6]Digitman © (03.08.05 13:21) [3]
Это-то да.
Не могу спорить, т.к. понимаю, что скорее всего не прав.
Скажу лишь в оправдание, что мне привычнее такое поведение:
sub MyProc {
my $a = 'Some data';
return \$a;
}
и после вызова
my $ref_a = MyProc();
я получу не мертвый указатель, а именно указатель на 'Some data';
Это на самом деле мой чуть ли не первый опыт на Delphi.
Тем не мнее спасибо большое!
Slym (2005-08-03 14:30:00) [7]
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;
Digitman (2005-08-03 13:21:00) [8]
> DVladimir (03.08.05 13:08) [2]
> Да нет.
да ДА!!
причем здесь "около 1000 байт" ?
время жизни лок.переменной процедуры равно времени жизни процедуры !
DVladimir (2005-08-03 13:08:00) [9]Да нет.
Т.е. если я пишу
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));
прекрасно отрабатывает.
Lamer@fools.ua (2005-08-03 07:16:00) [10]>
Result:=PChar(b);
Это неправильно. После выхода из функции указатель станет невалидным.