Форум программистов, компьютерный форум, киберфорум
Delphi: WinAPI
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/8: Рейтинг темы: голосов - 8, средняя оценка - 4.50
0 / 0 / 0
Регистрация: 23.08.2019
Сообщений: 20
1

Как корректнее поместить/скопировать текст из LPWSTR в WideString?

23.08.2019, 22:17. Показов 1586. Ответов 6
Метки нет (Все метки)

Добрый день!

Системный COM-объект выдаёт/заполняет мне LPWSTR. Причём зачастую требует вызов CoTaskMemFree() после того как данная информация становится больше не нужна.
Я подумал, что мне будет гораздо сподручнее хранить копию этой информации как WideString, чем мыкаться с LPWSTR и CoTaskMemFree() (информация будет требоваться неизвестное продолжительное время).

Сперва я подумал. Потом погуглил. Ещё подумал. И наваял вот такой вариант:
Первый вариант
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
function Test_01(...): WideString;
var Str: WideString; StrLen: DWORD;
begin
Result := '';
StrLen := 0;
// МетодВозвращающийРазмерНеобходимогоБуфера( ... , Word(nil^) , StrLen )
if StrLen > 0 then
   begin
   SetLength(Str, StrLen);
   ZeroMemory(PWideChar(Str), StrLen * SizeOf(Str[Low(Str)]));
   // МетодЗаполняющийБуферСодержимымСтроки( ... , PWord(PWideChar(Str))^ , StrLen )
   Result := Str;
   end;
Первая проблема оказалась в том, что судя по всему последний символ в строке Str получается "нуль-символ". Если я попытаюсь сделать конкатенацию типа ShowMessage('BEGIN>>' + Test_01(...) + '<<END');, то получаю сообщение вида BEGIN>>SomeText, остальное тупо пропадает.

Это оказалось возможным побороть двумя способами:
1) Задавать длину на единицу меньше: SetLength(Str, StrLen - 1);
2) Делать Result := Trim(Str);
У первого явный недостаток - буфер-то по факту меньше чем ожидается! Опасно? Хотя вот вполне себе работает, возможно оно само уже с некоторым запасом выделяется?
У второго побезопаснее, но просто не корректно - если ж и в начале и в конце строки и ожидаются пробельные символы, и они как бы как раз-таки все нужны?

Кстати мне пришлось делать финты вида Word(nil^) и PWord(...)^, потому что в документации прямо написано "указатель", но в заголовочниках Делфи почему-то var Word. Что вообще рекомендуется делать в таких случаях?

Попытавшись найти другие подходы, обнаружил более архаичный, но чуть более близкий к стилю Си++:
Второй вариант
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Test_02(...): WideString;
var Str: array of WideChar; StrLen: DWORD;
begin
Result := '';
StrLen := 0;
// МетодВозвращающийРазмерНеобходимогоБуфера( ... , Word(nil^) , StrLen )
if StrLen > 0 then
   begin
   SetLength(Str, StrLen);
   ZeroMemory(PWideChar(Str), StrLen * SizeOf(Str[0])); // надо ли тут и в строке ниже писать PWideChar(@Str[0]) ?
   // МетодЗаполняющийБуферСодержимымСтроки( ... , PWord(PWideChar(Str))^ , StrLen )
   Result := Str; // как корректно сделать здесь ?
   end;
end;
Вопрос 1: Лучше писать PWideChar(@Str[0]), или сойдёт PWideChar(Str)? То что на Рио и так и так работает я вижу.
Но как правильнее?
Вопрос 2: Компилятор не пускает Result := Str;, оно и понятно. Если я напишу типа PWideChar(Str) - работает, а если напишу WideString(Str) - хаха, почему-то копируется только половина строки. Что это за фокус такой?? 0___о ??
Аналогично, как правильнее?
Спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.08.2019, 22:17
Ответы с готовыми решениями:

Как скопировать текст из википедии вместе с формулами и поместить в Word?
Необходимо скопировать текст из Википедии вместе с картинками формул и поместить в microsoft word...

Как поместить текст в скобки?
Random r = new Random(); int i = r.Next(0, 36); textBox4.Text =...

Как поместить текст в PictureBox?
Возможно ли в си шарп элементу PictureBox присвоить текст, т.е. поместить текст в сам PictureBox??...

Как скопировать текст?
Напишите код код копировать виделений текст при нажатиє на кнопку?

6
Продавец времени
5015 / 2775 / 635
Регистрация: 12.03.2015
Сообщений: 13,477
23.08.2019, 23:35 2
Насколько я знаю, LPCWSTR - это PWideChar, то есть указатель. А если известно значение указателя и размер данных, на которые он указывает, то можно скопировать эти данные в предварительно выделенный кусок памяти. Например, с помощью функции move().

Не вижу, в чом проблема-то...
0
880 / 583 / 178
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
25.08.2019, 18:47 3
LPWSTR это * wchar_t. LPCWSTR это const * wchar_t.
Насколько я знаю, в Делфи нет достаточно точно аналогичных механизмов, так что и то и то будет просто PWideChar.

Цитата Сообщение от Edgar Wine Посмотреть сообщение
... требует вызов CoTaskMemFree() ...
В ваших примерах вы что-то как раз нигде это не вызывали. И там вы сами выделяете память, CoTaskMemFree по идее не нужен.
А в первом варианте кажется даже копирования не будет. Хотя сейчас уже точно не помню.

Цитата Сообщение от Edgar Wine Посмотреть сообщение
Если я напишу типа PWideChar(Str) - работает, а если напишу WideString(Str) - хаха, почему-то копируется только половина строки. Что это за фокус такой?
Это как так? А если например половина строки "12345"? %)
0
4932 / 3840 / 1278
Регистрация: 14.04.2014
Сообщений: 17,729
Записей в блоге: 18
25.08.2019, 21:26 4
а что функции типа StrNew уже не работают ?
0
880 / 583 / 178
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
25.08.2019, 22:52 5
хм... Только она и принимает PWideChar и возвращает тоже PWideChar.
Тогда уж может скорее WideCharToString() или OleStrToString()?

Добавлено через 22 минуты
Хотя судя по всему некий "буфер" и так и так потребуется...
0
0 / 0 / 0
Регистрация: 23.08.2019
Сообщений: 20
27.08.2019, 01:14  [ТС] 6
krapotkin, GoodWeather, спасибо, попробую!

Добавлено через 1 минуту
А функция CoTaskMemFree() немного в другом месте просто...

Добавлено через 2 минуты
Если бы я мог задать "12345", то я бы попробовал. =)
У меня попадались строки из шести символов, и при
Delphi
1
Result := WideString(Str);
в WideString оказывалось только три символа.
0
0 / 0 / 0
Регистрация: 23.08.2019
Сообщений: 20
13.10.2019, 15:33  [ТС] 7
Сперва стал использовать WideCharToString() - и всё прекрасно работало, насколько я мог наблюдать, по крайней мере все данные получались корректные.

Потом мне что-то щёлкнуло - "У меня же тут всюду COM/OLE, так может идеологически корректнее будет использовать OleStrToString()??"...
Взял и заменил всюду первое на второе. Ну а что? Входящий единственный параметр одинаковый, возврат функций тоже, и логически должны делать одно и то же...

А оно взяло и резко сломалось. Любой вызов OleStrToString() в любом месте кода приводит к вылету в трубу (где WideCharToString() работает штатно).
Так-то я в своём коде уже давно обратно поменял, но мне просто очень интересно - а что это было-то вообще, почему??
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.10.2019, 15:33

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

Как поместить текст в буфер обмена?
Как поместить текс в буфер обмена? всё что выдаёт гугл - не то, я помню копировал текст при...

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

Как корректнее сравнить две строки с временем
Здравствуйте, подскажите пожалуйста в одном вопросе. Я из внешнего файла &quot;достаю время&quot; в таком...

Как корректнее организовать анимацию двумерного графика
Доброго времени суток! Я новичок в OpenGL. Есть задача на мобильном устройстве (IOS, OpenGL ES)...

Как скопировать текст из PDF ?
Добрый день! Помогите скопировать текст из документа ПДФ. Открывал файл разными программами и на...

Как скопировать текст из Flash?
Нужно скопипастить лекции с данного сайта, для распечатки в черном белом варианте:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.