Я работаю в C ++ под Mac OS X (10.8.2), и недавно я столкнулся с необходимостью использования функций C ++ 11, которые доступны через компилятор clang ++ с использованием libc ++ stdlib.
Однако мне также нужно использовать некоторые устаревшие библиотеки, скомпилированные и связанные с libstdc ++ (из MacPorts).
При этом я получил ошибки компоновки, поскольку заголовки устаревших библиотек, например, std::string
, необходимо разрешить против std::__1::basic_string
(то есть реализация libc ++ std::string
) вместо std::basic_string
реализация.
Есть ли способ смешать две библиотеки в процессе разработки (например, с помощью флагов некоторых препроцессоров?)
То, что вы видите, это использование встроенные пространства имен для достижения версии ABI.
Что это значит:
Libstdc ++ std::string
это другая структура данных, чем в libc ++ std::string
, Первый — это счетный дизайн, а второй — нет. Хотя они совместимы с API, они не совместимы с ABI. Это означает, что если вы создаете std::string
с libstdc ++, а затем передать его другому коду, связанному с libc ++, принимающий код подумает, что у него есть libc ++ std::string
, То есть получатель не будет иметь понятия, что он должен увеличивать или уменьшать счетчик ссылок.
Без встроенных пространств имен результатом будет ошибка времени выполнения. Лучшее, на что вы можете надеяться, это крушение. В случае встроенных пространств имен эта ошибка времени выполнения преобразуется в ошибку времени ссылки.
Вам программист libstdc ++ std::string
и libc ++ std::string
похож на того же типа. Но для компоновщика они выглядят как совершенно разные типы (ключ к std::__1
Пространство имен). И ссылка компоновщика верна. Oни являются совершенно разные типы.
Так что да, вы можете манипулировать некоторыми флагами препроцессора, чтобы связать вещи. Но тогда у вас будет чертовское время, отлаживающее возникающие ошибки времени выполнения.
Единственный способ сделать то, что вы хотите, это сделать так, чтобы интерфейсы между этими библиотеками не включали std::
такие типы, как string
, Например, вы можете передать массивы char
вместо. Вы даже можете перенести владение памятью из кода, связанного с libstdc ++, в код, связанный с libc ++, и наоборот (оба они будут сбрасываться в один и тот же пул malloc).
Других решений пока нет …