C++
Характеристики связи
Поиск…
Вступление
Спецификация привязки сообщает компилятору компилировать объявления таким образом, чтобы их можно было связывать вместе с декларациями, написанными на другом языке, например C.
Синтаксис
- extern string-literal { declaration-seq ( opt )}
- ехЬегп строкового литерала декларация
замечания
Стандарт требует, чтобы все компиляторы поддерживали extern "C"
, чтобы позволить C ++ быть совместимым с C и extern "C++"
, который может использоваться для переопределения спецификации привязки и восстановления значения по умолчанию. Другие поддерживаемые спецификации привязки определены реализацией .
Обработчик сигналов для Unix-подобной операционной системы
Поскольку обработчик сигнала будет вызываться ядром с использованием соглашения о вызове C, мы должны сообщить компилятору использовать соглашение C-вызова при компиляции функции.
volatile sig_atomic_t death_signal = 0;
extern "C" void cleanup(int signum) {
death_signal = signum;
}
int main() {
bind(...);
listen(...);
signal(SIGTERM, cleanup);
while (int fd = accept(...)) {
if (fd == -1 && errno == EINTR && death_signal) {
printf("Caught signal %d; shutting down\n", death_signal);
break;
}
// ...
}
}
Создание заголовка библиотеки C, совместимого с C ++
Заголовок библиотеки AC обычно можно включить в программу на C ++, так как большинство объявлений действительны как для C, так и для C ++. Например, рассмотрим следующий foo.h
:
typedef struct Foo {
int bar;
} Foo;
Foo make_foo(int);
Определение make_foo
отдельно компилируется и распределяется с заголовком в виде объекта.
Программа C ++ может #include <foo.h>
, но компилятор не будет знать, что функция make_foo
определена как символ C и, вероятно, попытается найти ее с искаженным именем и не сможет ее найти. Даже если он может найти определение make_foo
в библиотеке, не все платформы используют одни и те же соглашения о вызовах для C и C ++, а компилятор C ++ будет использовать соглашение о вызове C ++ при вызове make_foo
, что может вызвать ошибку сегментации, если make_foo
ожидается, что его вызывают с помощью соглашения о вызове C.
Способ устранения этой проблемы состоит в том, чтобы обернуть почти все объявления в заголовке во extern "C"
блоке extern "C"
.
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Foo {
int bar;
} Foo;
Foo make_foo(int);
#ifdef __cplusplus
} /* end of "extern C" block */
#endif
Теперь, когда foo.h
включен в программу C, он будет просто отображаться как обычные объявления, но когда foo.h
будет включен из C ++-программы, make_foo
будет находиться внутри extern "C"
блока extern "C"
и компилятор будет знать, что искать unmangled name и использовать соглашение вызова C.