Каков эффект объявления 'extern "C" в заголовке для общей библиотеки C ++? - PullRequest
6 голосов
/ 06 апреля 2010

Исходя из этого вопроса Я понимаю назначение конструкции в связывании библиотек C с кодом C ++. Теперь предположим следующее:

У меня есть общая библиотека '.so', скомпилированная с помощью компилятора C ++. Заголовок имеет 'typedef stuct' и ряд объявлений функций. Если заголовок включает внешнюю декларацию "C" ...

#ifdef __cplusplus
extern "C"
{
#endif

  // typedef struct ...;
  // function decls

#ifdef __cplusplus
}
#endif

... каков эффект? В частности, мне интересно, есть ли какие-либо вредные побочные эффекты этого объявления, поскольку разделяемая библиотека скомпилирована как C ++, а не C.

Есть ли какая-либо причина иметь внешнюю "C" декларацию в этом случае?

Ответы [ 5 ]

12 голосов
/ 06 апреля 2010

Это важно, чтобы компилятор не называл mangle. C ++ использует искажение имен для дифференциации функций с перегрузками операторов.

Запустите "/ usr / bin / nm" для двоичного файла, чтобы увидеть, что C ++ делает с именами ваших функций: _ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E

extern "C" предотвращает искажение этого имени.

IIRC, что позволяет программе динамически связывать символы во время выполнения. Это типично для архитектур типа "плагин".

4 голосов
/ 06 апреля 2010

При компиляции C ++ имя метода изменяется (искажение) - и вы не сможете вызывать этот метод из другой dll / exe, которая использует C.

Чтобы сохранить имя класса и метода, которое вынеобходимо скомпилировать их как "C" без искажения имени.

Библиотека по-прежнему является библиотекой C ++, но некоторые ее объявления (в блоке extern "c") предоставляются как методы на языке C.

3 голосов
/ 06 апреля 2010

Объявление #ifdef защищенное extern должно сообщать компоновщикам C, что символы имеют записи таблицы символов C (unmangled). #ifdef гарантирует отсутствие эффекта в коде (файле), скомпилированном компилятором C.

0 голосов
/ 07 апреля 2010

#ifdef в этом примере означает, что только компилятор C ++ увидит extern, упаковывающий файл заголовка, что будет означать, что он будет генерировать не искаженные имена. Компилятор C не видит extern (что он не понимает), но всегда выдает не искаженные имена.

Это означает, что компиляторы C и C ++ будут создавать одинаковые символы в своих объектных файлах, поэтому, какой бы компилятор не создавал объектный код для объявленных функций, все объектные файлы будут успешно связаны, поскольку символы имеют одинаковую связь и одинаковое имя.

Не должно быть никаких последствий для статического связывания или связывания с общей библиотекой.

0 голосов
/ 07 апреля 2010

Одним из недостатков использования extern "C" для API C ++ является то, что он предотвращает перегрузки функций:

extern "C"
{
    // ILLEGAL - C linkage does not support function overloading
    void foo(int x);
    void foo(const char *str);
}
...