>void (*pf1)(int); // указатель на функцию С++
>extern "С" void (*pf2)(int); // указатель на функцию С
>pf1 = pf2; // ошибка: pf1 и pf2 имеют разные типы
Директива компоновки, использованная для функции, применяется также и к любым указателям на нее, используемым как тип возвращаемого значения или параметр.
>// f1() - функция С, ее параметр также является указателем на функцию С
>extern "С" void f1(void(*)(int));
Это объявление свидетельствует о том, что >f1()
является функцией языка С, которая не возвращает никаких значений. Она имеет один параметр в виде указателя на функцию, которая ничего не возвращает и получает один параметр типа >int
. Эта директива компоновки применяется как к самой функции >f1()
, так и к указателю на нее. Когда происходит вызов функции >f1()
, ей необходимо передать имя функции С или указатель на нее.
Поскольку директива компоновки применяется ко всем функциям в объявлении, для передачи функции С++ указателя на функцию С необходимо использовать определение типа (см. раздел 2.5.1):
>// FC - указатель на функцию С
>extern "С" typedef void FC(int);
>// f2 - функция С++, параметром которой является указатель на функцию С
>void f2(FC *);
Используя директиву компоновки в определении функции, написанной на языке С++, эту функцию можно сделать доступной для программы, написанной на другом языке.
>// функция calc() может быть вызвана из программы на языке С
>extern "С" double calc(double dparm) { /* ... */ }
Код, создаваемый компилятором для этой функции, будет соответствовать указанному языку.
Следует заметить, что типы параметров и возвращаемого значения в функциях для разных языков зачастую ограничены. Например, почти наверняка нельзя написать функцию, которая передает объекты нетривиального класса С++ программе на языке С. Программа С не будет знать о конструкторах, деструкторах или других специфических для класса операциях.
Чтобы позволить компилировать тот же файл исходного кода на языке С или С++, при компиляции на языке С++ препроцессор автоматически определяет имя >__cplusplus
(два символа подчеркивания). Используя эту переменную, при компиляции на С++ можно условно включить код, компилируемый только на С++:
>#ifdef __cplusplus
>// ok: компилируется только в С++
>extern "С"
>#endif
>int strcmp(const char*, const char*);
Взаимодействие директив компоновки и перегрузки функций зависит от конкретного языка. Если язык поддерживает перегрузку функций, то компилятор, обрабатывая директивы компоновки для того языка, вероятней всего, выполнит ее.
Язык С не поддерживает перегрузку функций, поэтому нет ничего удивительного в том, что директива компоновки языка С может быть определена только для одной из функций в наборе перегруженных функций:
>// ошибка: в директиве extern "С" указаны две одноименные функции