_declspec(dllexport) vector<MENUITEM> GetMenu(const WORD wMenuBaseID) {......}
в другой dll которая вызывает GetMenu из 1-ой:
pfnGetMenu = (vector<MENUITEM>(*)(WORD))::GetProcAddress((HINSTANCE)hLib,GETMENU)
vector<MENUITEM> pMenuItems = (*pfnGetMenu)(wMenuBaseID);//проблема с кучей
если из GetMenu возвращать указатель, все нормально, но встает вопрос как его удалять во второй dll, кучи-то разные?
делать vector<MENUITEM> глобальным не хочу, GetMenu(vector<MENUITEM>& inputVectorFromDll2..... тоже как-то некошерно
может кто знает как это обойтить?
стоит С++.NET (environment 2003 ver 7.1.3088) (статьи KB 168958,172396,309801 читал, экспорт классов меня не интересует)
Здравствуйте, Аноним, Вы писали:
А>если из GetMenu возвращать указатель, все нормально, но встает вопрос как его удалять во второй dll, кучи-то разные?
Если кучи разные, то даже передавать объект по ссылке нельзя: первый модуль его изменяет (пользуясь своей кучей), а второй — утилизирует (пользуясь своей). Бардак-с!
А>делать vector<MENUITEM> глобальным не хочу, GetMenu(vector<MENUITEM>& inputVectorFromDll2..... тоже как-то некошерно А>может кто знает как это обойтить?
Использовать рантайм Multithreaded DLL.
А>стоит С++.NET (environment 2003 ver 7.1.3088) (статьи KB 168958,172396,309801 читал, экспорт классов меня не интересует)
Ты и так уже пользуешься как-бы-экспортируемым вектором. К счастью, у него все методы инлайнятся и их дублирование не приводит к криминалу.
Как вариант: откажись от вектора, передавай указатели на массивы.
Перекуём баги на фичи!
Re[2]: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
15.12.04 13:48
Оценка:
К>Использовать рантайм Multithreaded DLL.
собирается с /MTd
К>Как вариант: откажись от вектора, передавай указатели на массивы.
так массивы придется грохать опять же не в той длл в какой они были созданы или я чего не догоняю?
Re[3]: возврат vector<My_Struct> из функции в .dll
Здравствуйте, <Аноним>, Вы писали:
К>>Использовать рантайм Multithreaded DLL. А>собирается с /MTd
К>>Как вариант: откажись от вектора, передавай указатели на массивы. А>так массивы придется грохать опять же не в той длл в какой они были созданы или я чего не догоняю?
ну дак экспортируй из той длл также ф-цию MyDllFree
... << RSDN@Home 1.1.3 stable >>
Re[4]: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
15.12.04 14:03
Оценка:
Здравствуйте, yxiie, Вы писали:
Y>Здравствуйте, <Аноним>, Вы писали:
К>>>Использовать рантайм Multithreaded DLL. А>>собирается с /MTd
К>>>Как вариант: откажись от вектора, передавай указатели на массивы. А>>так массивы придется грохать опять же не в той длл в какой они были созданы или я чего не догоняю?
Y>ну дак экспортируй из той длл также ф-цию MyDllFree
это все ведет к тому, что возвращаемый вектор придется делать глобальным, а я этого делать не хочу
Re[5]: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
15.12.04 14:39
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, yxiie, Вы писали:
Y>>Здравствуйте, <Аноним>, Вы писали:
К>>>>Использовать рантайм Multithreaded DLL. А>>>собирается с /MTd
К>>>>Как вариант: откажись от вектора, передавай указатели на массивы. А>>>так массивы придется грохать опять же не в той длл в какой они были созданы или я чего не догоняю?
Y>>ну дак экспортируй из той длл также ф-цию MyDllFree А>это все ведет к тому, что возвращаемый вектор придется делать глобальным, а я этого делать не хочу
никакой глобализации для этого не требуется. Просто сделай фабрику которая создает эти массивы функцией create и мочит их destroy и все. соответственно в экспортируемой функции DLLCreate вызывай у этого объекта create, а в DLLFree destroy
Re[6]: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
15.12.04 14:52
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, yxiie, Вы писали:
Y>>>Здравствуйте, <Аноним>, Вы писали:
К>>>>>Использовать рантайм Multithreaded DLL. А>>>>собирается с /MTd
К>>>>>Как вариант: откажись от вектора, передавай указатели на массивы. А>>>>так массивы придется грохать опять же не в той длл в какой они были созданы или я чего не догоняю?
Y>>>ну дак экспортируй из той длл также ф-цию MyDllFree А>>это все ведет к тому, что возвращаемый вектор придется делать глобальным, а я этого делать не хочу
А>никакой глобализации для этого не требуется. Просто сделай фабрику которая создает эти массивы функцией create и мочит их destroy и все. соответственно в экспортируемой функции DLLCreate вызывай у этого объекта create, а в DLLFree destroy
как я понял в библиотеке которая должна выдавать vector (в нашей терминологии длл1) будет жить некая сучность которая будет создавать вектор/массив, который далее будет возвращаться длл2 через вызов GetMenu, далее эта сучность будет грохать вектор/массив при выгрузке длл1? но тогда, по сути дела, эта сучность просто обертка вокруг вектора/массива, в чем преимущество, глобальный вектор/массив или вектор/массив с оберткой. к тому же длл1 должна экспортировать GetMenu в как можно более простом виде, идеальный вариант — GetMenu возвращающая вектор, это пользовательская библиотека, наворотов должно быть минимум
такой вопрос: сюда экспорт аллокаторов никак нельзя прикрутить, допустим передать аллокатор из длл2, в длл1 используя переданный аллокатор заполнить вектор и вернуть его а длл2?
Re[7]: возврат vector<My_Struct> из функции в .dll
ИМХО, можно написать инлайновый алокатор который выделяет память при помощи ::CoTaskMemAlloc() и удаляет ::CoTaskMemkFree(), и тогда проблемм с кучами не будет. Можно ещё написать классик class SuperVector: public std::vector; который переорделаяет оператор new и себя тоже создаёт через ::CoTaskMemAlloc(). Я думаю что должно работать. Сам не пробовал.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Аноним, Вы писали:
А>>>Здравствуйте, yxiie, Вы писали:
Y>>>>Здравствуйте, <Аноним>, Вы писали:
К>>>>>>Использовать рантайм Multithreaded DLL. А>>>>>собирается с /MTd
К>>>>>>Как вариант: откажись от вектора, передавай указатели на массивы. А>>>>>так массивы придется грохать опять же не в той длл в какой они были созданы или я чего не догоняю?
Y>>>>ну дак экспортируй из той длл также ф-цию MyDllFree А>>>это все ведет к тому, что возвращаемый вектор придется делать глобальным, а я этого делать не хочу
А>>никакой глобализации для этого не требуется. Просто сделай фабрику которая создает эти массивы функцией create и мочит их destroy и все. соответственно в экспортируемой функции DLLCreate вызывай у этого объекта create, а в DLLFree destroy
А>как я понял в библиотеке которая должна выдавать vector (в нашей терминологии длл1) будет жить некая сучность которая будет создавать вектор/массив, который далее будет возвращаться длл2 через вызов GetMenu, далее эта сучность будет грохать вектор/массив при выгрузке длл1? но тогда, по сути дела, эта сучность просто обертка вокруг вектора/массива, в чем преимущество, глобальный вектор/массив или вектор/массив с оберткой. к тому же длл1 должна экспортировать GetMenu в как можно более простом виде, идеальный вариант — GetMenu возвращающая вектор, это пользовательская библиотека, наворотов должно быть минимум
А>такой вопрос: сюда экспорт аллокаторов никак нельзя прикрутить, допустим передать аллокатор из длл2, в длл1 используя переданный аллокатор заполнить вектор и вернуть его а длл2?
Re[7]: возврат vector<My_Struct> из функции в .dll
[]
> такой вопрос: сюда экспорт аллокаторов никак нельзя прикрутить, допустим передать аллокатор из длл2, в длл1 используя переданный аллокатор заполнить вектор и вернуть его а длл2?
Сделай алокатор, который будет выделять память как HeapAlloc(GetProcessHeap(), ...) и передавай между dll вектор с таким алокатором.
-- Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[8]: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
15.12.04 16:24
Оценка:
Здравствуйте, MaximE, Вы писали:
>> такой вопрос: сюда экспорт аллокаторов никак нельзя прикрутить, допустим передать аллокатор из длл2, в длл1 используя переданный аллокатор заполнить вектор и вернуть его а длл2?
ME>Сделай алокатор, который будет выделять память как HeapAlloc(GetProcessHeap(), ...) и передавай между dll вектор с таким алокатором.
а использовать обычный аллокатор не получиться, допустим как-нибудь так :
(в экспортируемой функции)
PS: menuItems передается вызывающей стороной
вроде такая последовательность проходит, но вектор почему-то остается пустым, где туплю?
По поводу сделать аллокатор самому: ссылку на пример или на ценные указания не бросишь? а то я в STL чайник.... мне бы по-простецки: делай раз, делай два.....
Здравствуйте, Аноним, Вы писали:
А>как заставить работать следующий код
А>в 1-ой dll:
А>
А> _declspec(dllexport) vector<MENUITEM> GetMenu(const WORD wMenuBaseID) {......}
А>
Лучше всего никак. По большому счёту, гонять объекты (а также ссылки и указатели на них) через границу DLL — нельзя. И исключения, в частности, тоже.
/**
* Returns menu items associated with a base ID.
*
* @param baseID The base menu ID.
*
* @param buffer Points to a buffer allocated by the client. The function will
* fill this buffer with menu items associated with baseID.
*
* @param bufferSize On input: specifies the maximum number of elements that
* can be copied into buffer.
* On output: contains the number of elements copied.
*
* @return A nonzero value in case of success.
* Zero if an error occured.
*/
_declspec(dllexport) BOOL GetMenu(WORD baseID, MENUITEM* buffer, DWORD* bufferSize)
{
try
{
......;
return TRUE;
}
catch (...)
{
return FALSE;
}
}
было бы лучше. Потом, при импорте, заворачивай вызовы функций DLL в любые обёртки, в том числе классовые:
Re[2]: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
15.12.04 17:25
Оценка:
Здравствуйте, Centaur, Вы писали:
C>Лучше всего никак. По большому счёту, гонять объекты (а также ссылки и указатели на них) через границу DLL — нельзя. И исключения, в частности, тоже.
как же жить-то тогда,в простые типы все не запихнешь
C>было бы лучше. Потом, при импорте, заворачивай вызовы функций DLL в любые обёртки, в том числе классовые:
я GetMenu не импортирую, через GetProcAddress вызываю
GetMenu(WORD baseID, MENUITEM* buffer, DWORD* bufferSize) — скучно это все
Re[3]: возврат vector<My_Struct> из функции в .dll
Здравствуйте, Аноним, Вы писали:
C>>Лучше всего никак. По большому счёту, гонять объекты (а также ссылки и указатели на них) через границу DLL — нельзя. И исключения, в частности, тоже. А>как же жить-то тогда,в простые типы все не запихнешь
С тех пор, как изобрели сериализацию, всё можно «запихнуть» в char*.
C>>было бы лучше. Потом, при импорте, заворачивай вызовы функций DLL в любые обёртки, в том числе классовые: А>я GetMenu не импортирую, через GetProcAddress вызываю
Это неважно. Объектной обёртке по барабану.
А>GetMenu(WORD baseID, MENUITEM* buffer, DWORD* bufferSize) — скучно это все
Нда? Не хочешь DLL со скучным интерфейсом, напиши COM-сервер. Или .NET assembly. Вот тогда обхохочешься…
Re[9]: возврат vector<My_Struct> из функции в .dll
wrote:
> а использовать обычный аллокатор не получиться, допустим как-нибудь так :
Тебе же написали, что для "обычного" алокатора, который пользует "обычный" operator new, тебе нужно обеспечить, чтобы все модули в твоем проекте линковались с одной и той-же multithreaded runtime dll.
-- Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 delta
Re[10]: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
16.12.04 11:17
Оценка:
Здравствуйте, MaximE, Вы писали:
ME>wrote:
>> а использовать обычный аллокатор не получиться, допустим как-нибудь так :
ME>Тебе же написали, что для "обычного" алокатора, который пользует "обычный" operator new, тебе нужно обеспечить, чтобы все модули в твоем проекте линковались с одной и той-же multithreaded runtime dll.
а я и написал, что линкуется с /MTd или надо обязательно собирать с /MD?
со статической линковкой не подходит что-ли ?
Re: возврат vector<My_Struct> из функции в .dll
От:
Аноним
Дата:
21.07.09 10:14
Оценка:
в 1-ой dll:
Re[11]: Re: возврат vector<My_Struct> из функции в .dll
Здравствуйте, Аноним, Вы писали:
А>а я и написал, что линкуется с /MTd или надо обязательно собирать с /MD? А>со статической линковкой не подходит что-ли ?
Вот что пишет Джефри Рихтер по этому поводу:
Важно понимать, что единое адресное пространство состоит из одного исполняемого модуля и нескольких DLL-модулей. Одни из них могут быть скомпонованы со статически подключаемой библиотекой С/C++, другие — с DLL-версией той же библиотеки, а третьи (написанные не на С/C++) вообще ею не пользуются. Многие разработчики допускают ошибку, забывая, что в одном адресном пространстве может одновременно находиться несколько библиотек С/C++. Взгляните на этот код:
VOID EXEFunc()
{
PVOID pv = DLLFunc();
// обращаемся к памяти, на которую указывает pv;
// предполагаем, что pv находится в С/C++-куче EXE-файла
free(pv);
}
PVOID DLLFunc()
{
// выделяем блок в С/C++-куче DLL
return(malloc(100));
}
Ну и что Вы думаете? Будет ли этот код правильно работать? Освободит ли EXE-функция блок, выделенный DLL-функцией? Ответы на все вопросы одинаковы — может быть. Для точных ответов информации слишком мало. Если оба модуля (EXE и DLL) скомпонованы с DLL-версией библиотеки С/C++, код будет работать совершенно нормально. По если хотя бы один из модулей связан со статической библиотекой С/C++, вызов free окажется неудачным. Я не раз видел, как разработчики обжигались на подобном коде.
На самом деле проблема, решается очень просто, если в модуле есть функция, выделяющая память, в нем обязательно должна быть и противоположная функция, которая освобождает память. Давайте-ка перепишем предыдущий код так:
VOID EXEFunc()
{
PVOID pv = DLLFunc();
// обращаемся к памяти, на которую указывает pv,
// не делаем никаких предположений по поводу С/C++-кучи
DLLFreeFunc(pv);
}
PVOID DllFunc()
{
// выделяем блок в С/C++-куче DLL
PVOID pv = malloc(100);
return(pv);
}
BOOL DLLFreeFunc(PVOID pv)
{
// освобождаем блок, выделенный в С/C++-куче DLL
return(free(pv));
}
Этот код будет работать при любых обстоятельствах. Создавая свой модуль, не забывайте, что функции других модулей могут быть написаны на других языках, а значит, и ничего не знать о malloc и free. Не стройте свой код на подобных допущениях. Кстати, то же относится и к C++-операторам new и delete, реализованным с использованием malloc — free.
Вывод:
... либо возись с экспортированием функций, выделяющих и освобождающих память, либо линкуйся с С++ библиотекой динамически. Если проект пишется исключительно на С++ и состоит из нескольких PE-файлов, то второй способ избавляет от любого подобного геморроя ... вот только redist придётся поставлять вместе с твоим софтом, но это мелочь по сравнению с преимуществами динамической линковки с С++ библиотекой.
:)
"Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
Здравствуйте, Аноним, Вы писали: А>а я и написал, что линкуется с /MTd или надо обязательно собирать с /MD? А>со статической линковкой не подходит что-ли ?
"Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.