×
Traktatov.net » Язык программирования C++. Пятое издание » Читать онлайн
Страница 696 из 714 Настройки

>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 "С" указаны две одноименные функции