| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > WideString в DLL |
| Автор: aktuba 26.2.2007, 08:32 | ||||
| Не так давно я описывал http://forum.vingrad.ru/topic-136180/view-all.html. Сегодня вот нашел немного инфы на эту тему, точнее на тему использования WideString в DLL. Думаю, это многим пригодится, т.к. ни в одной книге, ни на других форумах подобного не встречал. Итак, вкратце: при использовании WideString НЕ НАДО никакого выделения памяти под строки, НЕ НАДО подключать никакие доп. модули и т.д. В общем не надо НИЧЕГО!!! Не верите? Попробуйте: Код DLL:
Код программы:
Все. Компилируем и проверяем. Странно... Работает Теперь небольшое объяснение. Все прекрасно знают, что в EXE и в DLL менеджеры памяти разные и именно из-за этого и возникают проблемы при передаче строк из программы в dll и обратно. Но, при использовании WideString, используется не обычный менеджер памяти, а специальный - системный. Специальный менеджер сделан для совместимости с COM. И этот менеджер памяти используется один на всех, поэтому WideString можно безопасно передавать и без использования ShareMem, FastShareMem и т.д. - просто в этом случае вы будете терять время на перекодировку в Unicode и обратно. Теперь по поводу выделения/освобождения памяти под WideString. При работе с WideString используются функции SysAllocString/SysReallocString/SysFreeString, которые можно вызвать явно или, как делает Delphi, неявно. Плюс к этому, в отличии от AnsiString, где для определения момента освобождения памяти, занимаемой строкой, используется механизм подсчета ссылок, в WideString всегда используется явно. Т.е. при присваивании wstr1 := wstr2, для AnsiString это будет просто копирование указателя, а для WideString создание новой строки и копирование содержимого wstr2 в созданную строку. Думаю, это многим поможет... |
| Автор: Quadr0 26.2.2007, 12:29 |
| ... |
| Автор: aktuba 26.2.2007, 12:31 | ||||||||
Да нет, мне кажется ты немного заблуждаешься. Или Delphi умнее, чем мы думаем и использует то, что необходимо в данной ситуации =). Для примера:
В отличии от твоего кода - я использую русский текст. Вот что дает дебагер: ![]() Здесь видно, что не только адреса ссылок на переменные разные, но и адрес нахождения самих данных различается. Но, пойдем дальше...
Снова не верно. Смотрим скрин: ![]() Снова видим, что никакого перехода к _LStrLAsg нет в природе. Все на уровне работы с WideString, ну и соответственно, используется SysRealloc, как я и написал в начале.
Снова повторю - неверно. Для WideString используется системный менеджер памяти, что наглядно видно из скринов. Правда есть подозрение, что в предыдущих версиях Delphi используется стандартный... Я же говорю про BDS2006/TurboDelphi... P.S.: пока писал - Quadr0 откоментил, но думаю скрины и пояснения многим помогут... |
| Автор: Alexeis 26.2.2007, 12:54 | ||
Все тестил на Delphi7. Там используется именно _LStrLAsg. В любом случае использование недокументированых возможностей сопрежено с большими проблемами совместимости версии. Раз в документации этого нет, значит Borland не обязяна сохранять эту систему в будущем. Непойму чем так усложняет жизнь простое указание модуля FastShareMem? |
| Автор: aktuba 26.2.2007, 13:10 | ||||||
Сейчас посмотрел на Delphi 7, там используется тоже самое, что и на BDS, т.е. к _LStrLAsg перехода нет. К сожалению не могу выложить скрин, т.к. D7 установлен на ноуте без инета...
Вот выдержка из хелпа D7:
|
| Автор: Alexeis 26.2.2007, 13:23 | ||||||
| Упс не догядел. Это был фрагмент линуксового кода Да уж и в семерке
p1 и p2 указывают на разные области памяти, тогда как
Указывают на одну. Добавлено @ 13:31 Да пожалуй основываясь на
Можно смело не использовать ни каких FastshareMem. |
| Автор: aktuba 26.2.2007, 13:36 |
| Alexeis, не хочется снова указывать ошибку, а приходится =((( - во втором коде замени AnsiString на WideString и все встанет на места. p1 и p2 будут указывать на разные области памяти.... |
| Автор: Alexeis 26.2.2007, 13:39 | ||||
Тогда еще небольшое дополнение к
Функция SysReAllocStringLen вообще виндовая и не принадлежит самому приложению. Память выделяется и уничтожается внешним, как для DLL так и для программы, менеджером памяти.
|
| Автор: Alexeis 26.2.2007, 14:15 |
| В связи с этим хочется развеять еще один скользкий вопрос. Считается, что использование Pchar вместо AnsiString позволяет также избавиться от проблем с менеджером памяти. Однако часто можно увидеть ситуацию, когда память для Pchar выделяется при помощи GetMem или New. Такой ход является очень опасным и допустим, только в случае если память выделенная GetMem освобождается в том же модуле, что и была выделена иначе нужно использовать HeapAlloc, GlobalAlloc. |
| Автор: Alexeyt 26.2.2007, 16:21 |
| aktuba, Alexeis, Спасибо за информацию. Очень полезно (у меня есть кое-какие DLL). |
| Автор: MetalFan 23.3.2007, 08:57 |
http://delphiworld.narod.ru/base/delphi_com.html мотаем до самого конца.... ы? |