C++
Specyfikacja powiązań
Szukaj…
Wprowadzenie
Specyfikacja powiązań mówi kompilatorowi, aby kompilował deklaracje w sposób, który pozwala na połączenie ich z deklaracjami napisanymi w innym języku, takim jak C.
Składnia
- extern string-literal { deklaracja-seq ( opt )}
- zewnętrzna deklaracja dosłowna
Uwagi
Standard wymaga, aby wszystkie kompilatory obsługiwały extern "C"
, aby umożliwić C ++ zgodność z C, oraz extern "C++"
, która może być użyta do zastąpienia załączonej specyfikacji powiązania i przywrócenia domyślnej. Inne obsługiwane specyfikacje powiązań są zdefiniowane w implementacji .
Procedura obsługi sygnałów dla systemu operacyjnego typu Unix
Ponieważ jądro wywołuje procedurę obsługi sygnału za pomocą konwencji wywoływania C, musimy poinformować kompilator, aby używał konwencji wywoływania C podczas kompilacji funkcji.
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;
}
// ...
}
}
Dostosowanie nagłówka biblioteki C do C ++
Nagłówek biblioteki AC można zwykle włączyć do programu C ++, ponieważ większość deklaracji jest poprawna zarówno w C, jak i C ++. Rozważmy na przykład następujący foo.h
:
typedef struct Foo {
int bar;
} Foo;
Foo make_foo(int);
Definicja make_foo
jest oddzielnie kompilowana i dystrybuowana wraz z nagłówkiem w formie obiektowej.
Program w C ++ może #include <foo.h>
, ale kompilator nie będzie wiedział, że funkcja make_foo
jest zdefiniowana jako symbol C i prawdopodobnie spróbuje poszukać go ze zniekształconą nazwą i nie uda się go zlokalizować. Nawet jeśli może znaleźć definicję make_foo
w bibliotece, nie wszystkie platformy używają tych samych konwencji wywoływania dla C i C ++, a kompilator C ++ użyje konwencji wywoływania C ++ podczas wywoływania make_foo
, co może spowodować błąd segmentacji, jeśli make_foo
oczekuje, że zostanie wywołany zgodnie z konwencją wywoływania C.
Rozwiązaniem tego problemu jest zawinięcie prawie wszystkich deklaracji w nagłówku w extern "C"
bloku 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
Teraz, gdy foo.h
jest dołączony z programu C, będzie wyglądał jak zwykłe deklaracje, ale kiedy foo.h
zostanie dołączony z programu C ++, make_foo
będzie znajdować się w extern "C"
bloku extern "C"
, a kompilator będzie wiedział, że szuka niezmienioną nazwę i użyj konwencji wywoływania C.