MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Несовместимость dll, lib и a между компиляторами"
Answer 880893
Несовместимость бинарных модулей (далее, для краткости, просто "модулей"), произведенных разными компиляторами, определяется в основном следующими тремя аспектами:
Разные правила декорирования имен экспортируемых символов
Разное устройство объектов стандартной библиотеки
Разные правила расположения полей структур в памяти
Первый пункт характерен фактически только для С++: в Си существует набор характерных для конкретной аппаратной платформы соглашений о вызове (например, stdcall, fastcall и cdecl для x86), которые довольно четко прописывают правила декорирования имен. Второй пункт относится и к Си и к С++, но в Си не очень много "объектов стандартной библиотеки" - в голову приходит только FILE*, и экспортировать его через границы модулей нет никакого смысла.
Таким образом да, действительно можно сказать, что С++ "хуже" чем Си в плане бинарной совместимости. Это разумеется не значит, что не нужно на нем писать, это лишь значит, что на границе модулей нужно использовать интерфейс в стиле Си (либо использовать стандартизированный объектно-ориентированный интерфейс, например Component Object Model в Windows).
Есть ли способы делать двоичные библиотеки максимально совместимыми? Чтобы написанная однажды библиотека dll могла быть подключена в самых разных языках без боли и страданий?
Использование DLL на С/С++ в других языках это больше чем вопрос бинарного интерфейса (например, в них может просто не быть концепции заголовочных файлов, указателей и т.п.), но обычно да, библиотека с интерфейсом в стиле Си может быть использована и из других языков с тем или иным количеством дополнительных телодвижений.
Рекомендации для обеспечения максимальной бинарной совместимости:
Экспортируйте через границы бинарного модуля только простые функции с припиской
extern "C"
(т.е, никаких классов, шаблонов, перегруженных функций, пространств имен и т.п.)Передавайте через границы модулей только простые типы, указатели на них и указатели на функции.
Если все же передаете структуры, сделайте первым членом структуры ее размер. Это позволит, если вы натолкнетесь на различия по выравниванию полей, обнаружить несоответствие в общем размере структуры и хотя бы нормально вернуть ошибку.
Не передавайте через границы модулей объекты стандартной библиотеки, например указатели FILE*.
Блоки динамической памяти должны освобождаться всегда в том же модуле, в котором были выделены. Т.е., если библиотека возвращает программе-клиенту указатель на блок памяти, выделенный malloc внутри себя, она должна предоставлять специальную функцию для его освобождения (вызывающую внутри себя free), вместо того, чтобы полагаться на вызов free в программе-клиенте.
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.