![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Возвращение строки 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. Ты этого хочешь ?