Директива компоновки может существовать в двух формах: одиночной и составной. Директивы компоновки не могут располагаться в определении класса или функции. Некоторые директивы компоновки должны присутствовать в каждом объявлении функции.
В качестве примера рассмотрим некоторые из функций языка С, объявленные в заголовке cstdlib
:
//
//
//
extern "С" size_t strlen(const char *);
//
extern "С" {
int strcmp(const char*, const char*);
char *strcat(char*, const char*);
}
Первая форма состоит из ключевого слова extern
, сопровождаемого строковым литералом и "обычным" объявлением функции.
Строковый литерал указывает язык, на котором написана функция. Используемый компилятор обязан поддерживать директивы компоновки для языка С. Компилятор может поддерживать директивы компоновки и для других языков, например extern "Ada"
, extern "FORTRAN"
и т.д.
Та же директива компоновки может быть применена к нескольким функциям одновременно. Для этого их объявления заключают в фигурные скобки после директивы компоновки. Эти фигурные скобки служат для группировки объявлений, к которым применяется директива компоновки. Эти фигурные скобки игнорируются, а имена функций, объявленных в их пределах, видимы, как будто функции были объявлены вне фигурных скобок.
Составная форма объявления применима ко всему файлу заголовка. Например, заголовок cstring
языка С++ может выглядеть следующим образом.
// составная директива компоновки
extern "С" {
#include
//
}
Когда директива #include
заключена в фигурные скобки составной директивы компоновки, все объявления обычных функций в файле заголовка будут восприняты как написанные на языке, указанном в директиве компоновки. Директивы компоновки допускают вложенность, т.е. если заголовок содержит функцию с директивой компоновки, на данную функцию это не повлияет.
extern "С"
Язык, на котором написана функция, является частью ее типа. Чтобы объявить указатель на функцию, написанную на другом языке программирования, следует использовать директиву компоновки. Кроме того, указатели на функции, написанные на других языках, следует объявлять с той же директивой компоновки, что и у самой функции:
//
extern "С" void (*pf) (int);
Когда указатель pf
используется для вызова функции, созданный при компиляции код подразумевает, что происходит обращение к функции С.
Тип указателя на функцию С не совпадает с типом указателя на функцию С++. Указатель на функцию С не может быть инициализирован (или присвоен) значением указателя на функцию С++ (и наоборот). Как и при любом другом несовпадении типов, попытка присвоения указателя с другой директивой компоновки приведет к ошибке:
void (*pf1)(int); //
extern "С" void (*pf2)(int); //
pf1 = pf2; //
Директива компоновки, использованная для функции, применяется также и к любым указателям на нее, используемым как тип возвращаемого значения или параметр.
//
extern "С" void f1(void(*)(int));
Это объявление свидетельствует о том, что f1()
является функцией языка С, которая не возвращает никаких значений. Она имеет один параметр в виде указателя на функцию, которая ничего не возвращает и получает один параметр типа int
. Эта директива компоновки применяется как к самой функции f1()
, так и к указателю на нее. Когда происходит вызов функции f1()
, ей необходимо передать имя функции С или указатель на нее.