Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: std::wstring в параметре функции DLL  (Прочитано 20450 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 28-09-2012 03:27 » 

имею ли я право делать следующее:  есть динамически подключаемая DLL , в ней экспортированная функция , например такая

Код: (C++)
extern "C" void WINAPI GetString(std::wstring& str)
{
     str.resize(100,0); //изменение кучи основного модуля из DLL
}

Если же память необходимо выделить до вызова - как это лучше организовать?
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 28-09-2012 03:51 » 

Леш, разве сишная функция совместима с ссылкой на объект?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 28-09-2012 03:53 » 

считай её указателем )
Код: (C++)
extern "C" void WINAPI GetString(std::wstring* str)
{
     str->resize(100,0); //изменение кучи основного модуля из DLL
}
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 28-09-2012 04:10 » 

Нет, Леш, так делать нельзя. Во-первых, DLL ничего не знает о методах объекта, тем более интерфейс сишный. Во-вторых, выделять и освобождать память надо в одном месте, т.к. менеджеры кучи и сами кучи могут быть разные.
Чтобы управлять кучей основного модуля, DLL должен импортировать себе ее malloc/free и вызывать именно их. Сомневаюсь еще на счет совместимости различных версий runtime-библиотек. По этому правильно будет: выделять и освобождать память в одном месте.

Вот чувак тоже задумался и почитал классиков: http://www.cyberforum.ru/cpp-beginners/thread370440.html
Правда, у него движение в обратную сторону.
« Последнее редактирование: 28-09-2012 04:16 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 28-09-2012 04:33 » 

>>выделять и освобождать память в одном месте
да, я это помню. Но больно громоздко получается.

Добавлено через 1 минуту и 31 секунду:
я сделал так - вызываю функцию DLL , где выделяю память на объект std::wstring (и ещё парочку нужных типов) , потом указатель на этот объект уже передаю в DLL, чтобы она с ним работала. Ну и "удалятор" тоже как функция в DLL - примерно такая штука получается:

Код: (C++)
CDLL*pDLL=...; //обёртка для DLL

std::wstring* str=0;
pDLL->New(&str); //*str - объект строки
   pDLL->GetString(str);
   //...
pDLL->Del(&str);

но если параметров больше, чем 1, то такой огород получается Улыбаюсь)
« Последнее редактирование: 28-09-2012 04:41 от Алексей1153++ » Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 28-09-2012 06:34 » 

void * лучше.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 28-09-2012 10:43 » 

Импорт stl-классов в DLL на практике как-то делают (можно погуглить), но это не так чтобы тривиально (разбирается, например, тут, во втором ответе: http://stackoverflow.com/questions/1881494/how-to-expose-stl-list-over-dll-boundary) - такого рода правки без серьёзных оснований лучше, как по мне, не вносить, потому что хрупкость конструкции резко возрастает, требуются экспертные знания, чтобы это при поддержке не сломать.

upd. Вот статья от MS в тему: http://support.microsoft.com/kb/168958/ru
« Последнее редактирование: 28-09-2012 10:45 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 28-09-2012 16:35 » 

Вад, что-то мне мой вариант больше понравился ))
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 28-09-2012 18:11 » 

Алексей1153++, ну, я сам тоже похожую схему предпочитаю, но отдаю так только "простую" память, а stl-контейнеры из dll возвращать не рискую: всё-таки, версии stl могут быть разные при сборке dll и клиентского кода - соответственно, и реализации класса wstring могут быть разными.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 28-09-2012 18:49 » 

Леш, посмотри такую схему: указатели в DLL передаются только для копирования информации. Туже строку принял, создал свой объект, скопировал и вернул указатель. Основной модуль, соотв., должен этот указатель удалить функцией DLL.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 29-09-2012 15:38 » new

Вад, RXL, да я вообще склоняюсь к радикальной мере - обмен через XML Отлично  Так как эта обвеска вся такая громоздкая (и, как выясняется, тоже небезопасная).

По схеме , предложенной Ромой, кстати.
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 29-09-2012 19:19 » 

Еще безопаснее обмен через временный файл. Передать в DLL можно открытый handle или константную строку пути. Но по моему это изврат.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zubr
Гость
« Ответ #12 : 30-09-2012 05:35 » 

Обмен памятью внутри процесса с использованием внешнего файла - имхо, кривовато. Уж тогда кошернее будет использовать файлмаппинг...
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 30-09-2012 14:19 » 

нет, файл точно отпадает. Максимум XML )  Достаточно гибко

Завтра опробую
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 01-10-2012 04:37 » 

кстати, а как думаете, может быть лучше передавать в функцию DLL указатель на функцию, которая будет выделять память в основном модуле ?

таким образом вызывающий никогда не "забудет" , что нужно удалять память (поскольку намёки на это всегда перед глазами при вызове) . В случае же, когда результат нужно очищать вызовом функции в DLL, это можно и забыть, тогда будет утечка

а ?
Записан

zubr
Гость
« Ответ #15 : 01-10-2012 07:04 » 

Имхо, проще, передавать в функцию указатель на указатель выделенной памяти средствами Windows, к примеру VirtualAlloc. Этот указатель будет сто пудов ликвидным в любом модуле процесса. Внутри длл-функции можно копировать в std::wstring и работать с этой структурой. По завершению функции можно создать новый блок памяти нужного размера (удалив старый) куда скопировать результат работы с std::wstring и передать его в двойной указатель.
Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 01-10-2012 10:15 » 

Если уж полёт фантазии пошёл, предлагаю организовать передачу данных из DLL через сокеты Улыбаюсь Ну, или пайпы - кому как больше нравится.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #17 : 01-10-2012 20:34 » 

кстати, а как думаете, может быть лучше передавать в функцию DLL указатель на функцию, которая будет выделять память в основном модуле ?

"Всё уже украдено до нас" (с) Ага

Проблема стара как мир, и решение примерно такого же возраста. Лёш, ф-я получает в качестве параметров а) указатель на буфер, и б) - ссылку на размер. Вызывается 2 раза: 1 - указатель нуль, по возвращению в ссылке необходимый размер, после этого вызывающий создаёт У СЕБЯ буфер нужного размера, и вызывает ф-ю второй раз, с уже ненулевым указателем. Таким образом, вызывающий отвечает полностью за выделение памяти, да и размер буфера в ф-ю передавать невредно.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 02-10-2012 03:18 » 

Джон, это совсем неудобно, так как DLL должна хранить у себя результат. А когда многопоточность ? А когда несколько вызывающих ? У меня будет так
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 02-10-2012 05:45 » 

Я не понимаю, почему за память не может отвечать DLL? Чего тут сложного?
Код: (C++)
extern "C" void _declspec(dllexport) createA(void *a, unsigned long *size = NULL);
extern "C" void _declspec(dllexport) createB(void *b, unsigned long *size = NULL);
// ...
extern "C" void _declspec(dllexport) createZ(void *z, unsigned long *size = NULL);

extern "C" void _declspec(dllexport) destroy(void *any);
Куча функций создаёт что-то в блоках памяти, клиент получает указатели и (по желанию) размеры блоков. После окончания использования поручает DLL очистить память. Можно договориться, что: функции с префиксом create выделяют память, и нужно вызывать destroy; функции с префиксом get память не выделяют, destroy вызывать не нужно.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 02-10-2012 05:58 » 

Дим, так надо же помнить, кто выделял память...

А нельзя ли импортировать в DLL функции malloc/free из уже подлинкованной к основному модулю runtime-библиотеки?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 02-10-2012 06:34 » 

Dimka, сложного ничего Улыбаюсь
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #22 : 02-10-2012 07:39 » 

Джон, это совсем неудобно, так как DLL должна хранить у себя результат. А когда многопоточность ? А когда несколько вызывающих ? У меня будет так

Лёш, ну винда функционирует по такому принципу уже лет двадцать, и ничего, не жужжит. Ага И с многопоточностью, и с несколькими вызывающими.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 02-10-2012 11:37 » 

Цитата: RXL
Дим, так надо же помнить, кто выделял память...

А нельзя ли импортировать в DLL функции malloc/free из уже подлинкованной к основному модулю runtime-библиотеки?
А потом вспоминать, чей malloc вызывать и в каких случаях Улыбаюсь

Чего страшного запоминании? Нужен объект, который помнит, какому create какой destroy соответствует. Те же COM обращаются к счётчику ссылок - не забывают Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #24 : 02-10-2012 11:50 » 

Джон, ну это же не значит, что это нужно повторять Улыбаюсь У меня будет по 2 раза одних и тех же вычислений/операций, не хочу так )))
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #25 : 02-10-2012 13:33 » 

Ну, во-первых, чтобы ты ни сделал, ты будешь повторять. Ага А во-вторых, почему одних и тех же? В первом случае тебе буфер заполнять не надо.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines