Зачем нам нужен extern "C"{ #include <foo.h> } в C++?

extern "C" определяет, как cxx должны называться символы linkage в сгенерированном объектном extern-c файле. Если функция объявлена extern-c ​​без внешнего "C", имя символа c++ в объектном файле будет использовать extern-c изменение имени C++. Вот extern-c пример.

Данный test.C выглядит name-mangling так:

void foo() { }

Компиляция и перечисление extern-c символов в объектном файле linkage дает:

$ g++ -c test.C
$ nm test.o
0000000000000000 T _Z3foov
                 U __gxx_personality_v0

Функция foo на самом name-mangling деле называется "_Z3foov". Эта linkage строка содержит, помимо прочего, информацию cpp о типе возвращаемого значения cpp и параметрах. Если вы вместо extern-c этого напишете test.C следующим c++ образом:

extern "C" {
    void foo() { }
}

Затем скомпилируйте extern-c и посмотрите символы:

$ g++ -c test.C
$ nm test.o
                 U __gxx_personality_v0
0000000000000000 T foo

Вы получаете extern-c связь C. Имя функции «foo» в c++ объектном файле просто «foo», и linkage в нем нет всей причудливой cpp информации о типе, которая name-mangling возникает из-за искажения extern-c имени.

Обычно вы включаете cpp заголовок в extern "C" {}, если c++ код, который идет с ним, был c++ скомпилирован с помощью компилятора cpp C, но вы пытаетесь вызвать cpp его из C++. Когда вы делаете linkage это, вы сообщаете компилятору, что c++ все объявления в заголовке extern-c будут использовать связь cxx C. Когда вы связываете свой cxx код, ваши файлы .o будут cxx содержать ссылки на «foo», а linkage не на «_Z3fooblah», что, как linkage мы надеемся, соответствует extern-c тому, что находится в библиотеке, с extern-c которой вы связываетесь.

Большинство name-mangling современных библиотек устанавливают extern-c защиту вокруг таких заголовков, чтобы name-mangling символы объявлялись с правильным cxx связыванием. например во c++ многих стандартных заголовках extern-c вы найдете:

#ifdef __cplusplus
extern "C" {
#endif

... declarations ...

#ifdef __cplusplus
}
#endif

Это гарантирует, что name-mangling когда код C++ включает заголовок, символы cxx в вашем объектном файле совпадают cxx с тем, что есть в библиотеке name-mangling C. Вам нужно поместить extern cxx "C" {} вокруг заголовка C linkage только в том случае, если extern-c он устарел и еще не имеет c++ этих охранников.

c++

linkage

name-mangling

extern-c

2022-09-08T21:19:30+00:00