Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Указатели


Жора с Бора ©   (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;


Наверх

Титульная страница Поиск, карта сайта Написать письмо