Ответ
При связывании кода на C и C++ необходимо учитывать различия в компоновке (linking), обработке исключений и управлении ресурсами. Основные правила:
-
Соглашение о компоновке (Name Mangling): C++ компилятор "декорирует" имена функций, кодируя информацию о типах параметров для поддержки перегрузки. C компилятор этого не делает. Чтобы C++ код мог вызывать C-функции, их объявления нужно обернуть в
extern "C".header.h (общий для C и C++):
#ifdef __cplusplus extern "C" { #endif void c_library_function(int param); // Объявление C-функции #ifdef __cplusplus } #endif -
Исключения: Исключения C++ не должны пересекать границу C-кода. C-функции не знают о механизме раскрутки стека C++. Любые исключения должны быть перехвачены и обработаны внутри C++ кода до возврата в C.
-
Совместимость типов и ABI: Используйте только POD-типы (Plain Old Data), которые гарантированно одинаковы в C и C++: базовые типы (
int,double), структуры без методов, объединения, указатели. Избегайте передачиstd::string,std::vectorили объектов с виртуальными функциями. -
Управление памятью: Память, выделенная с помощью
mallocв C, должна освобождатьсяfree. Память, выделеннаяnewв C++, должна освобождатьсяdelete. Нельзя смешивать аллокаторы. Лучшая практика — предоставлять из C-библиотеки парные функции создания/уничтожения.// C-библиотека struct MyCStruct* create_struct() { return (struct MyCStruct*)malloc(sizeof(struct MyCStruct)); } void destroy_struct(struct MyCStruct* p) { free(p); } // C++ код extern "C" { #include "my_c_lib.h" } void foo() { MyCStruct* obj = create_struct(); // Вызов C-функции // ... работа с obj ... destroy_struct(obj); // Освобождение через C-функцию } -
Инициализация и завершение: Если C-библиотека требует вызова функций инициализации (
init_lib()) и деинициализации (shutdown_lib()), C++ код должен явно их вызывать, обычно в конструкторе/деструкторе класса-обёртки (RAII).