Безопасно ли возвращать std::wstring из DLL?
Согласно некоторым старым вопросам Stackru ( невозможно передать std::wstring через DLL, C++ DLL возвращает указатель на std::liststd::wstring
потому что нет гарантии, что основная программа имеет такое же определение std::wstring
и, следовательно, это может привести к аварии.
Однако, в http://en.cppreference.com/w/cpp/string/basic_string, кажется, std::wstring
может использоваться взаимозаменяемо с WCHAR
массив сейчас:
(Начиная с C++11) Элементы basic_string хранятся непрерывно, то есть для basic_string s, &*(s.begin() + n) == &*s.begin() + n для любого n в [0, s.size()) или, что эквивалентно, указатель на s[0] может быть передан в функции, которые ожидают указатель на первый элемент массива CharT[].
Я проверил это, пройдя &s[0]
к функции WINAPI, которая ожидала WCHAR*
буфера и оказалось работать (std::wstring
был правильно заполнен результатами WINAPI). Так как std::wstring
по-видимому, можно рассматривать как WCHAR
Теперь я решил вернуться к этому вопросу: std::wstring
безопасно вернуться из DLL? Почему или почему нет?
1 ответ
Ничего не изменилось в отношении передачи объектов C++ через границы DLL. Это по-прежнему не разрешено по той же причине, что и раньше. Модуль на другой стороне границы может иметь другое определение класса.
Дело в том, что &s[0]
допустимый модифицируемый указатель на символьный массив на самом деле не актуален. Потому что std::basic_string
это намного больше, чем просто массив символов.
Помните, что каждая реализация std::basic_string
может иметь различную внутреннюю память. Может иметь другую реализацию для operator[]
, Может быть выделено из другой кучи. И так далее.
Я думаю, можно с уверенностью предположить, что никогда не будет допустимо передавать объекты C++ через общие границы DLL. Это возможно только в том случае, если вы гарантируете, что обе стороны границы связаны с одним и тем же экземпляром времени выполнения.