Запомните одну вещь, прежде чем читать дальше: Мой ответ исходит из точки зрения написания переносимого кода, который можно использовать в приложениях, составленных из модулей, скомпилированных в разных компиляторах. Это может включать разные версии или даже разные уровни исправлений одного и того же компилятора.
Как я могу использовать stl-классы в моем
DLL-интерфейс?
Ответ: Вы часто не можете 1 .
Причина: STL - это библиотека кодов, а не двоичная библиотека, как DLL. У него нет ни одного ABI, который гарантированно будет одинаковым везде, где вы можете его использовать. Действительно, STL означает « Стандарт Библиотека шаблонов», но ключевое слово здесь, помимо Стандартного, - Шаблон .
Стандарт определяет методы и члены данных, которые должен предоставлять каждый класс STL, и определяет, что эти методы должны делать; но не более В частности, в стандарте не указано, как разработчики компиляторов должны реализовывать определенные стандартом функциональные возможности. Разработчики компиляторов могут предоставить реализацию класса STL, который добавляет функции-члены и переменные-члены , а не , перечисленные в Стандарте, при условии, что те члены, которые * определены в Стандарте, все еще там и делай то, что говорит Стандарт.
Может быть, пример в порядке. Класс basic_string
определен в Стандарте как имеющий определенные функции-члены и переменные. Фактическое определение в Стандарте составляет почти 4 страницы, но вот его фрагмент:
namespace std {
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string {
[snip]
public:
// 21.3.3 capacity:
size_type size() const;
size_type length() const;
size_type max_size() const;
void resize(size_type n, charT c);
void resize(size_type n);
size_type capacity() const;
void reserve(size_type res_arg = 0);
void clear();
bool empty() const;
[snip]
};
Рассмотрим функции-члены size()
и length()
. В Стандарте нет ничего, что определяло бы переменные-члены для хранения этой информации. Действительно, переменные-члены не определены вообще, даже для хранения самой строки. Так как это реализовано?
Ответ - много разных способов. Некоторые компиляторы могут использовать переменную-член size_t
для хранения размера и char*
для хранения строки. Другой может использовать указатель на какое-то другое хранилище данных, которое хранит эти данные (это может иметь место в реализации с подсчетом ссылок). Фактически, разные версии или даже уровни исправлений одного и того же компилятора могут изменить эти детали реализации. Вы не можете положиться на них. Итак, реализация MSVC 10 может выглядеть так:
namespace std {
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string {
[snip]
char* m_pTheString;
};
size_t basic_string::size() const { return strlen(m_pTheString;) }
... Тогда как MSVC 10 с пакетом обновления 1 может выглядеть следующим образом:
namespace std {
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string {
[snip]
vector<char> m_TheString;
};
size_t basic_string::size() const { return m_TheString.size(); }
Я не говорю, что они делают похожи на это, я говорю, что они могли бы. Дело в том, что фактическая реализация зависит от платформы, и у вас действительно нет возможности узнать, что это будет где-то еще.
Теперь предположим, что вы используете MSVC10 для написания DLL, которая экспортирует этот класс:
class MyGizmo
{
public:
std::string name_;
};
Что такое sizeof(MyGizmo)
?
Предполагая мои предложенные реализации выше, под MSVC10 это будет sizeof(char*)
, но под SP1 это будет sizeof(vector<char>)
. Если вы напишите приложение в VC10 SP1, которое использует DLL, размер объекта будет выглядеть иначе, чем на самом деле. Двоичный интерфейс изменен.
Подробнее об этом см. Стандарты кодирования C ++ (Amazon ссылка ) № 63.
1 : " Вы часто не можете " На самом деле вы можете экспортировать компоненты стандартной библиотеки или любые другие компоненты библиотеки кода (например, Boost) с достаточной степенью надежности, когда вы иметь полный контроль над цепочками инструментов и библиотеками.
Основная проблема заключается в том, что с библиотеками исходного кода размеры и определения вещей могут различаться для разных компиляторов и разных версий библиотеки. Если вы работаете в среде, где вы контролируете обе эти вещи везде, где используется ваш код, то у вас, вероятно, не будет проблем. Например, в торговой фирме, где все системы написаны собственными силами и используются только собственными силами, возможно, это удастся сделать.