Проблема передачи std :: string через границы DLL с Visual Studio - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть DLL, которая содержит такой код:

class Info {
    int a
    int b
    int c
    std::string str1;
    std::string str2;
};

__declspec(dllexport) class C {
    Info getInfo();
}

Я компилирую этот код с помощью Visual Studio 2015, и вызов C::getInfo() прекрасно работает в моей системе.

Теперь кто-то другой пытается использовать DLL, и он также использует Visual Studo 2015. Вызов проходит хорошо, но строки не содержат доступных данных.Даже отладчик сообщает «Ошибка чтения символов строки», и программа вылетает при попытке ее прочитать.

Была также похожая проблема с std::vector, которую я мог решить, вставив код, создавший вектор.

Мне кажется, что либо другой человек использует другую версию STL, либо компилятор каким-то образом создает другую структуру памяти для std::string (хотя он утверждает, что использует настройки по умолчанию).

Возможно ли это?Я видел, что существуют разные обновления для VS 2015, и у нас могут не быть установлены те же самые обновления.

Есть какие-либо рекомендации по исправлению этого?Я не могу перейти на char* без значительного нарушения API.Большинство пользователей даже не используют Visual Studio (или Windows), поэтому до сих пор это не было проблемой.

1 Ответ

0 голосов
/ 13 декабря 2018

Боюсь, это жизнь.Если у вас нет точно того же компилятора (включая стандартную библиотеку C ++) и настроек компилятора, это не гарантированно сработает.Я не убежден с точки зрения стандартов C ++, что даже это гарантированно сработает.Почти невозможно построить ABI в C ++.В вашем конкретном примере нет гарантии, что struct будет построен с такими же характеристиками выравнивания.sizeof(std::string) значительно варьируется из-за оптимизации коротких строк, которая может даже настраиваться компилятором.

Альтернативы:

  1. Использовать связь C для экспортируемых функций и char *-стиль интерфейсов, которые выделяются и освобождаются вызывающей стороной (см. Windows API).(Никогда не выделяйте память на клиенте и не освобождайте ее в dll, и наоборот.)

  2. Убедитесь, что пользователь вашей библиотеки может собрать ее из исходных файлов.Рассматривайте распространение как статическую, а не динамическую библиотеку, поскольку с ней немного проще работать.

...