Я не согласен с точкой зрения Криса Бекке, хотя вижу преимущества его подхода.
Недостаток в том, что вы не можете создавать библиотеки служебных объектов, потому что вам запрещено делиться ими между библиотеками.
Расширение решения Криса
Как создать согласованные двоичные файлы DLL для версий VS?
Ваш выбор зависит от того, насколько разные компиляторы. С одной стороны, разные версии одного и того же компилятора могут обрабатывать выравнивание данных одинаково, и, таким образом, вы можете представлять структуры и классы в своих DLL. С другой стороны, вы можете не доверять компиляторам других библиотек или параметрам компиляции.
В Windows Win32 API они решали проблему через «обработчики». Вы делаете то же самое по:
1 - Никогда не подвергать структуру. Разоблачать только указатели (то есть указатель void *)
2 - Доступ к этим данным структуры осуществляется через функции , принимающие указатель в качестве первого параметра
3 - указатель этой структуры данные о распределении / освобождении находятся через функции
Таким образом, вы можете избежать перекомпиляции всего, когда ваша структура изменится.
C ++ способ сделать это - PImpl. См http://en.wikipedia.org/wiki/Opaque_pointer
Он имеет то же поведение, что и концепция void * выше, но с помощью PImpl вы можете использовать как RAII, инкапсуляцию, так и прибыль от строгой безопасности типов. Для этого потребуется совместимое оформление (тот же компилятор), но не одно и то же время выполнения или версия (если между версиями одинаковое оформление).
Другое решение?
Надеясь смешать библиотеки DLL из разных версий компиляторов / компиляторов - это либо повод для катастрофы (как вы объяснили в своем вопросе), либо утомительно, поскольку вы позволили отказаться от большинства (если не от всех) решений C ++ в своем коде базовое кодирование C или оба.
Мое решение будет:
1 - убедитесь, что все ваши модули скомпилированы с одинаковым компилятором / версией . Период.
2 - Убедитесь, что все ваши модули скомпилированы для ссылки динамически с тем же временем выполнения
3 - Убедитесь, что у вас есть «инкапсуляция» всех сторонних модулей , над которыми у вас нет контроля (невозможно компилировать с вашим компилятором), как совершенно справедливо объяснил Крис Бекке в Как сделать согласованные двоичные файлы DLL для версий VS? .
Обратите внимание, что не удивительно и не возмутительно, что все модули вашего приложения скомпилированы для одного и того же компилятора и одной и той же версии компилятора.
Не позволяйте никому говорить, что смешивание компиляторов - это хорошо. Это не. Свобода микширования компилятора для большинства людей - та же самая свобода, которой можно наслаждаться, выпрыгивая с вершины здания: вы можете делать это свободно, но обычно вы просто этого не хотите.
Мое решение позволяет вам:
1 - экспортировать классы и, таким образом, создавать настоящие некастрированные библиотеки C ++ (как вы должны делать, например, с __declspec (dllexport) Visual C ++)
2 - передать владение распределением (что происходит без вашего согласия при использовании встроенного и / или освобождающего встроенного кода или STL)
3 - не раздражаться проблемами , связанными с тем фактом, что каждый модуль имеет свою собственную версию среды выполнения (т.е. выделение памяти и некоторые глобальные данные, используемые API C или C ++)
Обратите внимание, что это означает, что вы не должны смешивать отладочную версию своих модулей с выпусками других модулей. Ваше приложение полностью отлажено или полностью выпущено.