Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 28-09-2012 03:27 » |
|
имею ли я право делать следующее: есть динамически подключаемая DLL , в ней экспортированная функция , например такая extern "C" void WINAPI GetString(std::wstring& str) { str.resize(100,0); //изменение кучи основного модуля из DLL } Если же память необходимо выделить до вызова - как это лучше организовать?
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #1 : 28-09-2012 03:51 » |
|
Леш, разве сишная функция совместима с ссылкой на объект?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 28-09-2012 03:53 » |
|
считай её указателем ) extern "C" void WINAPI GetString(std::wstring* str) { str->resize(100,0); //изменение кучи основного модуля из DLL }
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #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 »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 28-09-2012 04:33 » |
|
>>выделять и освобождать память в одном месте да, я это помню. Но больно громоздко получается. Добавлено через 1 минуту и 31 секунду:я сделал так - вызываю функцию DLL , где выделяю память на объект std::wstring (и ещё парочку нужных типов) , потом указатель на этот объект уже передаю в DLL, чтобы она с ним работала. Ну и "удалятор" тоже как функция в DLL - примерно такая штука получается: 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
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #5 : 28-09-2012 06:34 » |
|
void * лучше.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 28-09-2012 16:35 » |
|
Вад, что-то мне мой вариант больше понравился ))
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #8 : 28-09-2012 18:11 » |
|
Алексей1153++, ну, я сам тоже похожую схему предпочитаю, но отдаю так только "простую" память, а stl-контейнеры из dll возвращать не рискую: всё-таки, версии stl могут быть разные при сборке dll и клиентского кода - соответственно, и реализации класса wstring могут быть разными.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #9 : 28-09-2012 18:49 » |
|
Леш, посмотри такую схему: указатели в DLL передаются только для копирования информации. Туже строку принял, создал свой объект, скопировал и вернул указатель. Основной модуль, соотв., должен этот указатель удалить функцией DLL.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 29-09-2012 15:38 » |
|
Вад, RXL, да я вообще склоняюсь к радикальной мере - обмен через XML Так как эта обвеска вся такая громоздкая (и, как выясняется, тоже небезопасная). По схеме , предложенной Ромой, кстати.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #11 : 29-09-2012 19:19 » |
|
Еще безопаснее обмен через временный файл. Передать в DLL можно открытый handle или константную строку пути. Но по моему это изврат.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
zubr
Гость
|
|
« Ответ #12 : 30-09-2012 05:35 » |
|
Обмен памятью внутри процесса с использованием внешнего файла - имхо, кривовато. Уж тогда кошернее будет использовать файлмаппинг...
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 30-09-2012 14:19 » |
|
нет, файл точно отпадает. Максимум XML ) Достаточно гибко
Завтра опробую
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 01-10-2012 04:37 » |
|
кстати, а как думаете, может быть лучше передавать в функцию DLL указатель на функцию, которая будет выделять память в основном модуле ?
таким образом вызывающий никогда не "забудет" , что нужно удалять память (поскольку намёки на это всегда перед глазами при вызове) . В случае же, когда результат нужно очищать вызовом функции в DLL, это можно и забыть, тогда будет утечка
а ?
|
|
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #15 : 01-10-2012 07:04 » |
|
Имхо, проще, передавать в функцию указатель на указатель выделенной памяти средствами Windows, к примеру VirtualAlloc. Этот указатель будет сто пудов ликвидным в любом модуле процесса. Внутри длл-функции можно копировать в std::wstring и работать с этой структурой. По завершению функции можно создать новый блок памяти нужного размера (удалив старый) куда скопировать результат работы с std::wstring и передать его в двойной указатель.
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #16 : 01-10-2012 10:15 » |
|
Если уж полёт фантазии пошёл, предлагаю организовать передачу данных из DLL через сокеты Ну, или пайпы - кому как больше нравится.
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
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."
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #18 : 02-10-2012 03:18 » |
|
Джон, это совсем неудобно, так как DLL должна хранить у себя результат. А когда многопоточность ? А когда несколько вызывающих ? У меня будет так
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #19 : 02-10-2012 05:45 » |
|
Я не понимаю, почему за память не может отвечать DLL? Чего тут сложного? 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
Технический
Администратор
Offline
Пол:
|
|
« Ответ #20 : 02-10-2012 05:58 » |
|
Дим, так надо же помнить, кто выделял память...
А нельзя ли импортировать в DLL функции malloc/free из уже подлинкованной к основному модулю runtime-библиотеки?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 02-10-2012 06:34 » |
|
Dimka, сложного ничего
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
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
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #23 : 02-10-2012 11:37 » |
|
Дим, так надо же помнить, кто выделял память...
А нельзя ли импортировать в DLL функции malloc/free из уже подлинкованной к основному модулю runtime-библиотеки? А потом вспоминать, чей malloc вызывать и в каких случаях Чего страшного запоминании? Нужен объект, который помнит, какому create какой destroy соответствует. Те же COM обращаются к счётчику ссылок - не забывают
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #24 : 02-10-2012 11:50 » |
|
Джон, ну это же не значит, что это нужно повторять У меня будет по 2 раза одних и тех же вычислений/операций, не хочу так )))
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
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."
|
|
|
|