На основе этого вопроса я понимаю цель конструкции в соединении библиотек C с кодом C++. Теперь предположите следующее:
У меня есть '.so', совместно использовал библиотеку, скомпилированную с компилятором C++. Заголовок имеет 'определение типа stuct' и много объявлений функции. Если заголовок включает экстерна "C" объявление...
#ifdef __cplusplus
extern "C"
{
#endif
// typedef struct ...;
// function decls
#ifdef __cplusplus
}
#endif
... каков эффект? Конкретно я задаюсь вопросом, существуют ли какие-либо вредные побочные эффекты того объявления, так как общая библиотека компилируется как C++, не C.
Там какая-либо причина состоит в том, чтобы иметь экстерна "C" объявление в этом случае?
Это важно, чтобы компилятор не называл mangle. C ++ использует изменение имен, чтобы различать функции с перегрузками операторов.
Запустите "/ usr / bin / nm" для двоичного файла, чтобы увидеть, что C ++ делает с вашими именами функций: _ ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E
extern "C" предотвращает искажение этого имени.
IIRC, что позволяет программе динамически связывать символы во время выполнения. Это обычное явление для архитектур типа "плагин".
При компиляции C++ имя метода изменяется (mangling) - и вы не сможете вызвать этот метод из другой dll/exe, использующей C.
Чтобы сохранить имя класса и метода, вам нужно компилировать их как "C" без изменения имени.
Библиотека по-прежнему является библиотекой C++, но она раскрывает некоторые свои объявления (те, что в блоке extern "c") как методы C.
Одним из недостатков использования extern "C"
для C ++ API является то, что он предотвращает перегрузку функций:
extern "C"
{
// ILLEGAL - C linkage does not support function overloading
void foo(int x);
void foo(const char *str);
}
#ifdef
в примере означает, что только компилятор C ++ увидит extern
, обертывающий файл заголовка, что будет означать, что он будет создавать имена без искажений. Компилятор C не видит extern
(который он не понимает), но всегда создает неискаженные имена.
Это означает, что компиляторы C и C ++ будут создавать одни и те же символы в своих объектных файлах, поэтому какой бы компилятор ни создавал объектный код для объявленных функций, все объектные файлы будут успешно связаны, потому что символы имеют одинаковую связь и одно и то же имя.
Не должно быть никаких последствий ни для статического связывания, ни для связывания с разделяемой библиотекой.
Объявление #ifdef
guarded extern
должно сообщать компоновщикам C, что символы имеют записи таблицы C (несвязанные). #ifdef
гарантирует отсутствие эффекта в кодовой единице (файле), скомпилированной компилятором C.