Вопрос по dll, stl, c++ – Последствия использования std :: vector в экспортированной функции dll

16

У меня есть два dll-экспортируемых класса A и B. Объявление A содержит функцию, которая использует std :: vector в своей подписи, например:

<code>class EXPORT A{
 // ...
 std::vector<B> myFunction(std::vector<B> const &input);
};
</code>

(EXPORT - это обычный макрос для установки _declspec (dllexport) /_declspec (dllimport) соответственно.)

Читая о проблемах, связанных с использованием классов STL в интерфейсе DLL, я подытож

Использование std :: vector в интерфейсе DLL потребует компиляции всех клиентов этой DLL с одним и тем жеверси того же компилятора, потому что контейнеры STL не являются двоично-совместимыми. Еще хуже, в зависимости от использования этой DLL клиентами совместно с другими библиотеками DLL, «нестабильный» API DLL может сломать эти клиентские приложения, когда установлены обновления системы (например, пакеты Microsoft KB) (правда?).

Несмотря на вышесказанное, при необходимости std :: vector можно использовать в API DLL путем экспортаstd::vector<B> нравится

<code>template class EXPORT std::allocator<B>;
template class EXPORT std::vector<B>;
</code>

хотя это обычно упоминается в контексте, когда кто-то хочет использовать std :: vector как Член of A (http://support.microsoft.com/kb/168958)

В следующей статье службы поддержки Microsoft обсуждается, как получить доступ к объектам std :: vector, созданным в DLL, с помощью указателя или ссылки из исполняемого файла (http://support.microsoft.com/default.aspx?scid=kb;EN-US ; Q172396). Вышеупомянутое решение использоватьtemplate class EXPORT ...ажется, @ тоже применимо. Однако недостаток, подытоженный в первом пункте, кажется, остаетс

Чтобы полностью избавиться от проблемы, нужно обернуть std :: vector и изменить сигнатуруmyFunction, PIMPL и т.д ..

Мои вопросы:

Верно ли приведенное выше резюме или я что-то упустил?

Почему компиляция моего класса 'A' не генерирует предупреждение C4251 (класс 'std :: vector <_Ty>' должен иметь dll-интерфейс для использования клиентами ...)? У меня нет отключенных предупреждений компилятора, и я не получаю никаких предупреждений об использовании std :: vector вmyFunction в экспортированном классе А (с VS2005).

Что нужно сделать, чтобы правильно экспортироватьmyFunction в? Это реально просто экспортироватьstd::vector<B> и Б распределитель?

Какое значение имеет возврат значения std :: vector по значению? Предполагается, что исполняемый файл клиента был скомпилирован с другим компилятором (-version). Сохраняется ли проблема при возврате по значению, куда копируется вектор? Я думаю да. Аналогично для передачи std :: vector в качестве константы: мог получить доступ кstd::vector<B> (который может быть создан исполняемым файлом, скомпилированным с другим компилятором (-version)) может привести к возникновению проблем вmyFunction? Я думаю, да еще раз ..

Является ли последний пункт, указанный выше, действительно единственным чистым решением?

Большое спасибо заранее за ваш отзыв.

template class EXPORT std :: vector <B>; работает для получения всех функций-членов, экспортируемых / импортируемых должным образом. Как насчет шаблонных функций, которые не являются функциями-членами? Например. Оператор == ()? Начиная с VS 2012, теперь я получаю ошибки ссылок при сборке DLL, потому что функция сравнения векторов не определена. Kevin Hopps
Следующая ветка охватывает некоторые / связанные вопросы, но не все из нихнит jrg

Ваш Ответ

2   ответа
2

ваш список очень точен. Основной причиной этого является то, что DLL-to-DLL или DLL-to-EXE определяется на уровне операционной системы, в то время как интерфейс между функциями определяется на уровне компилятора. В некотором смысле, ваша задача похожа (хотя и несколько проще) на задачу взаимодействия клиент-сервер, когда клиент и сервер не имеют двоичной совместимости.

Компилятор отображает возможные пути импорта и экспорта DLL в конкретной операционной системе. Поскольку языковые спецификации дают компиляторам большую свободу, когда речь идет о двоичной компоновке пользовательских типов, а иногда даже встроенных типов (напомним, что точный размерint зависит от компилятора, при условии соблюдения минимальных требований к размеру), импорт и экспорт из DLL должны выполняться вручную для обеспечения совместимости на двоичном уровне.

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

Ммм ... но это означало бы, что те же проблемы существуют, если я заменюstd::vector<B> сint? Или до какой степени операционной системе удается сопоставить типы? jrg
@ user1043103 Вернувшись к моей последней работе на C, у нас были стандарты кодирования, которые требовали использовать толь#define -d вводит сигнатуры функций, которые мы экспортировали из наших DLL, избегая встроенных примитивов. Например, мы должны были использоватьINT32 вместо тогоint - предположительно, для сохранения совместимости между различными версиями компилятора. dasblinkenlight
0


Вместо прохожденияstd:vector, вы можете передатьQVector отQt библиотека.
Проблемы, которые вы цитируете, затем обрабатываются внутриQt библиотека, и вам вообще не нужно с этим сталкиваться.
Конечно, стоит использовать библиотеку и принять ее немного худшую производительность.
С точки зрения количества времени, затрачиваемого на кодирование и отладку, это решение того стоит.

Похожие вопросы