![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Указатели
Жора с Бора © (2013-07-22 11:07:00)Добрый день! Никогда не работал в Delphi, а вот тут пришлось поставить. Не могу разобраться с указателями. Есть внешняя stdcall dll. Там, к примеру, есть функция:
implementation
Function Version: PChar; stdcall;external 'mydll.DLL'
Делаю так:
procedure TfrmMain.cmd01Click(Sender: TObject);
var tmpString: ShortString;
p:PChar;
begin
p:=Version;
tmpString:=ShortString(p^);
txtdebug.Text:=tmpString;
end;
Возвращает 1.
Меняю объявление указателя на Pointer:
procedure TfrmMain.cmd01Click(Sender: TObject);
var tmpString: ShortString;
p:Pointer;
begin
p:=Version;
tmpString:=ShortString(p^);
txtdebug.Text:=tmpString;
end;
Возвращает .25.
Что ж такое, я точно знаю, что функция должна возвращать 1.25.
Как бы мне объявить указатель, чтобы все-же мое значение пришло целиком ко мне.
И еще, как в Delphi выводить переменные в отладку, в Edit все же не очень удобно. Спасибо!
Дмитрий (2013-08-27 18:46:00) [1]http://www.transl-gunsmoker.ru/2009/09/blog-post.html
icWasya (2013-07-22 14:35:00) [2]Ну, и еще если кто объяснит мне смысл того зоопарка. что я понаписал, буду премного благодарен.
Со строками есть несколько Compiller-Magic.
procedure TfrmMain.cmd01Click(Sender: TObject);
var
tmpString: ShortString;
p:PChar;
begin
p:=Version;
tmpString:=ShortString(p^);
txtdebug.Text:=tmpString;
end;
предположим, как в твоём примере функция Version выглядит так
char * Version()
{
return "1.25";
}
по буквам
1)
p:=Version;
Здесь ты получаешь из программы указатель на массив Char-ов и присваиваешь переменной типа указатель на Char.
2)
tmpString:=ShortString(p^);
Вот тут происходит две вещи
первая
p^тут происходит разыменование p. То есть берётся первый элемент массива - в твоём случае символ '1'. Пока всё штатно.
вторая
Ещё со времен паскаля существует преобразование Char->ShortString, описаное в руководстве по языку, то есть выражение типа Char неявно преобразуется в строку длиной в один символ и с содержимым, равным этому Char.
Поэтому tmpString = '1';
procedure TfrmMain.cmd01Click(Sender: TObject);
var
tmpString: ShortString;
p:Pointer;
begin
p:=Version;
tmpString:=ShortString(p^);
txtdebug.Text:=tmpString;
end;
1)
p:=Version;
Здесь ты получаешь из программы указатель на массив Char-ов и присваиваешь переменной типа указатель. В Си - эквивалент void*;
2)
tmpString:=ShortString(p^);
p^тут разыменование pуже невозможно, потому что безтиповый указатель.
Поэтому делается попытка преобразовать то, на что указывает pсразу в ShortString, безо всякой Compiller-Magic.
А ShortString устроена так - нулевой символ - это длина строки, а начиная с первого - содержимое строки.
И в результате в tmpString присваивается интересная строка - Length = 49, а содержимое = '.25'#0'мусор длиной в 45 символов'.
Можешь посмотреть в отладчике.
Но при присваивании такой строки в качестве текста в Едит, строка обрубится по первому нулевому символу.
И в результате в txtdebug покажется текст '.25';
И в завершении
совсем правильно
txtdebug.Text:=StrPas(Version);
И начиная с D-2 существует неявное преобразование PChar->AnsiString, и можно прямо писать
txtdebug.Text:=Version;
Как-то так
MBo (2013-07-22 12:08:00) [3]передавать с использованием прямого приведения типов PChar(StringVar)
RWolf (2013-07-22 12:08:00) [4]
Res:=Login(PChar(MyUser), PChar(MyPsw));
Жора с Бора (2013-07-22 12:02:00) [5]А обратно как корректно обработать?
Например вызвать такую функцию, есть 2 Edit'а txtLogin и txtPass ?
Function Login( AUser, APsw: PChar ): BOOL; stdcall;external 'mydll.DLL'
RWolf (2013-07-22 11:36:00) [6]
> [4]
да не нужно это всё.
присвоение PChar'а строке обрабатывается корректно — копированием в неё содержимого источника до первого нулевого символа.
Жора с Бора (2013-07-22 11:33:00) [7]Ну, и еще если кто объяснит мне смысл того зоопарка. что я понаписал, буду премного благодарен.
Жора с Бора (2013-07-22 11:32:00) [8]Благодарю, уже прочитал, что тип String это сам по себе указатель =)
Dennis I. Komarov (2013-07-22 11:30:00) [9]tmpString:=StrPas(p);
RWolf (2013-07-22 11:29:00) [10]
txtdebug.Text:=Version;