возврат vector<My_Struct> из функции в .dll
От: Аноним  
Дата: 15.12.04 12:40
Оценка:
как заставить работать следующий код

в 1-ой dll:

 _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 читал, экспорт классов меня не интересует)
Re: возврат vector<My_Struct> из функции в .dll
От: Кодт Россия  
Дата: 15.12.04 13:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>если из GetMenu возвращать указатель, все нормально, но встает вопрос как его удалять во второй dll, кучи-то разные?


Если кучи разные, то даже передавать объект по ссылке нельзя: первый модуль его изменяет (пользуясь своей кучей), а второй — утилизирует (пользуясь своей). Бардак-с!

А>делать vector<MENUITEM> глобальным не хочу, GetMenu(vector<MENUITEM>& inputVectorFromDll2..... тоже как-то некошерно

А>может кто знает как это обойтить?

Использовать рантайм Multithreaded DLL.

А>стоит С++.NET (environment 2003 ver 7.1.3088) (статьи KB 168958,172396,309801 читал, экспорт классов меня не интересует)


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

Как вариант: откажись от вектора, передавай указатели на массивы.
http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!
Re[2]: возврат vector<My_Struct> из функции в .dll
От: Аноним  
Дата: 15.12.04 13:48
Оценка:
К>Использовать рантайм Multithreaded DLL.
собирается с /MTd

К>Как вариант: откажись от вектора, передавай указатели на массивы.

так массивы придется грохать опять же не в той длл в какой они были созданы или я чего не догоняю?
Re[3]: возврат vector<My_Struct> из функции в .dll
От: yxiie Украина www.enkord.com
Дата: 15.12.04 13:53
Оценка:
Здравствуйте, <Аноним>, Вы писали:

К>>Использовать рантайм 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
От: Vruyr  
Дата: 15.12.04 15:47
Оценка:
ИМХО, можно написать инлайновый алокатор который выделяет память при помощи ::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
От: MaximE Великобритания  
Дата: 15.12.04 15:56
Оценка:
wrote:

[]

> такой вопрос: сюда экспорт аллокаторов никак нельзя прикрутить, допустим передать аллокатор из длл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 вектор с таким алокатором.


а использовать обычный аллокатор не получиться, допустим как-нибудь так :
(в экспортируемой функции)

__declspec(dllexport) DWORD GetMenu(vector<MENUITEM>& menuItems, const WORD wMenuBaseID)
{
  ..................
  MENUITEM menuItem;

  allocator<MENUITEM>::pointer ptr = menuItems.get_allocator().allocate(1);
  menuItem.wId = wMenuBaseID + 0;
  menuItem.fState = false;
  menuItem.pfn = Handler1;
  menuItems.get_allocator().construct(&ptr[0],menuItem);
  .............
}


PS: menuItems передается вызывающей стороной
вроде такая последовательность проходит, но вектор почему-то остается пустым, где туплю?
По поводу сделать аллокатор самому: ссылку на пример или на ценные указания не бросишь? а то я в STL чайник.... мне бы по-простецки: делай раз, делай два.....
Re: возврат vector<My_Struct> из функции в .dll
От: Centaur Россия  
Дата: 15.12.04 17:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>как заставить работать следующий код


А>в 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 в любые обёртки, в том числе классовые:
_declspec(dllimport) BOOL GetMenu(WORD baseID, MENUITEM* buffer, DWORD* bufferSize);

std::vector<MENUITEM> GetMenu(WORD baseID)
{
  const size_t BUFSIZE = много;
  MENUITEM result[BUFSIZE];
  DWORD size = BUFSIZE;
  if (!GetMenu(baseID, result, &size))
  {
    throw std::runtime_error("oops, sh!t happened");
  }
  return std::vector<MENUITEM>(result, result + size);
}
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
От: Centaur Россия  
Дата: 15.12.04 20:08
Оценка:
Здравствуйте, Аноним, Вы писали:

C>>Лучше всего никак. По большому счёту, гонять объекты (а также ссылки и указатели на них) через границу DLL — нельзя. И исключения, в частности, тоже.

А>как же жить-то тогда,в простые типы все не запихнешь

С тех пор, как изобрели сериализацию, всё можно «запихнуть» в char*.

C>>было бы лучше. Потом, при импорте, заворачивай вызовы функций DLL в любые обёртки, в том числе классовые:

А>я GetMenu не импортирую, через GetProcAddress вызываю

Это неважно. Объектной обёртке по барабану.

А>GetMenu(WORD baseID, MENUITEM* buffer, DWORD* bufferSize) — скучно это все


Нда? Не хочешь DLL со скучным интерфейсом, напиши COM-сервер. Или .NET assembly. Вот тогда обхохочешься…
Re[9]: возврат vector<My_Struct> из функции в .dll
От: MaximE Великобритания  
Дата: 15.12.04 21:03
Оценка:
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&lt;My_Struct> из функции в .dll
От: Аноним  
Дата: 21.07.09 10:14
Оценка:
в 1-ой dll:
Re[11]: Re: возврат vector<My_Struct> из функции в .dll
От: Rakafon Украина http://rakafon.blogspot.com/
Дата: 29.07.09 00:56
Оценка:
Здравствуйте, Аноним, Вы писали:

А>а я и написал, что линкуется с /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) Мейер Ансельм Ротшильд , банкир.
DLL
Re[11]: возврат vector<My_Struct> из функции в .dll
От: Rakafon Украина http://rakafon.blogspot.com/
Дата: 30.07.09 09:07
Оценка:
Здравствуйте, Аноним, Вы писали:
А>а я и написал, что линкуется с /MTd или надо обязательно собирать с /MD?
А>со статической линковкой не подходит что-ли ?

... также, для лучшего понимания решения ваших проблем, нелишним будет прочтение следующей статьи: Заметка о некоторых особенностях использования STL в DLL
Автор(ы): Роман Хациев
Дата: 27.02.2002
Если вы пытались работать с экземплярами классов STL, передавая их в DLL, или получая оттуда, а потом бросили это занятие из-за непонятных ошибок, возникающих в вашей программе, то эта заметка для вас. Даже если видимых проблем в вашей программе нет, то все равно прочитайте эту заметку, чтобы знать что делать, когда они появятся :)
"Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
DLL STL CRT Multithreaded
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.