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

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

Возвращение строки PChar, Delphi 2009 [XP]


Darvin ©   (2010-03-15 11:07:00) 

Здравствуйте!
Мне нужно написать функцию на Delphi 2009, чтобы она возвращала результат в формате PChar. Вот ее реализация:

function GetName(TestID: Integer; out Name: PChar): HResult;
var
 S : String;
begin
   S := uGetData.GetName(TestID);
   if S = '' then
     Result := NOT_FOUND
   else begin
     GetMem ( Name, (Length(S) + 1) * SizeOf(Char) );
     Name := PChar(S);
     Result := SUCCESS;
   end;
end;


Перед выходом в отладчике проверяю состояние Name. Оно содержит корректные данные, скажем 'Абрамов Иван Сергеевич'.

Потом вызываю ее следующим образом:

var
 Name : PChar;
begin
 ...
 GetName(TestID, Name);


И вот здесь получается Name = 'Абрамов <иероглифы>'.
В чем я не прав?
Особенность: Эта функция из COM - интерфейса, вызывается из другого приложения


Darvin   (2010-03-15 14:32:00) [1]

Накопал следующее:
 S := 'Привет!!!';
 Name := StrNew(PChar(S));
 StrDispose(Name);

Этот код работает


DVM   (2010-03-15 14:29:00) [2]


> Ответа нет...

ответ есть, см ниже


Darvin   (2010-03-15 14:28:00) [3]


> Убил память присвоением

я ЭТО понял. Я написал
> Значит, я неправильно присваиваю значение для Name

И задал вопрос:
> А как правильно?

Ответа нет...


DVM   (2010-03-15 14:27:00) [4]


> Darvin   (15.03.10 14:10) [7]


> Name := PChar(S);

вот этой строкой ты указатель Name переставил на другое место в памяти. Для копирования строки можно использовать например Move()


Anatoly Podgoretsky   (2010-03-15 14:15:00) [5]

> Darvin  (15.03.2010 14:10:07)  [7]

Убил память присвоением


Darvin   (2010-03-15 14:10:00) [6]

Экспериментируя пришел к следующему. Написал такой пример:

var
 S : String;
 Name : PChar;
begin
 S := 'Привет!!!';
 GetMem ( Name, 102 );
 Name := PChar(S);
 FreeMem ( Name );


При освобождении памяти возникает ошибка Invalid Pointer Operation. Значит, я неправильно присваиваю значение для Name. А как правильно?


DVM   (2010-03-15 12:04:00) [7]


> Darvin   (15.03.10 11:56) [3]

Очень плохо, когда функция сама выделяет память под строку. Так делают крайне редко и в исключительных случаях.

Гораздо лучше, если бы в функцию передавался указатель на уже выделенный в памяти буфер и размер выделенной памяти. Если же заранее неизвестно, сколько памяти надо выделить, то можно сделать так, чтобы та же функция при недостатке места в буфере, возвращала соответствующий код ошибки и размер необходимой памяти в какую либо переменную.

Так делается в WinAPI.


Darvin   (2010-03-15 12:02:00) [8]


> Главная S это строка с ограниченым сроком существования
> и GetMem неприменимо.

Да, GetMem на результативность не влияет, я ее убрал вообще, все работает, по крайней мере видимых сбоев нет.


> Слишком много ошибок.

А не сложно ли Вам указать их все?


Anatoly Podgoretsky   (2010-03-15 11:59:00) [9]

> Darvin  (15.03.2010 11:07:00)  [0]

Слишком много ошибок.
Главная S это строка с ограниченым сроком существования и GetMem неприменимо.


Darvin   (2010-03-15 11:56:00) [10]

Интересно! Поменял PChar на PAnsiChar, все заработало:

function GetName(TestID: Integer; out Name: PAnsiChar): HResult;
var
S : AnsiString;
begin
  S := uGetData.GetName(TestID);
  if S = '' then
    Result := NOT_FOUND
  else begin
    GetMem ( Name, (Length(S) + 1) * SizeOf(Char) );
    Name := PAnsiChar(S);
    Result := SUCCESS;
  end;
end;


Вызов:

var
Name : PAnsiChar;
begin
...
GetName(TestID, Name);

Вопрос. А если хочу с PWideChar?


Darvin   (2010-03-15 11:34:00) [11]

да. Но, если я указываю PWideChar, ничего не меняется


Игорь Шевченко   (2010-03-15 11:28:00) [12]

в D2009 PChar - это PWideChar. Ты этого хочешь ?


Наверх

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