Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КРАТКИЙ ОБЗОР С.doc
Скачиваний:
1
Добавлен:
26.10.2018
Размер:
2.11 Mб
Скачать

4.4 Связывание с программами на других языках

Программы на С++ часто содержат части, написанные на других языках, и наоборот, часто фрагмент на С++ используется в программах, написанных на других языках. Собрать в одну программу фрагменты, написанные на разных языках, или, написанные на одном языке, но в системах программирования с разными соглашениями о связывании, достаточно трудно. Например, разные языки или разные реализации одного языка могут различаться использованием регистров при передаче параметров, порядком размещения параметров в стеке, упаковкой таких встроенных типов, как целые или строки, форматом имен функций, которые транслятор передает редактору связей, объемом контроля типов, который требуется от редактора связей. Чтобы упростить задачу, можно в описании внешних указать условие связывания. Например, следующее описание объявляет strcpy внешней функцией и указывает, что она должна связываться согласно порядку связывания в С:       extern "C" char* strcpy(char*, const char*); Результат этого описания отличается от результата обычного описания       extern char* strcpy(char*, const char*); только порядком связывания для вызывающих strcpy() функций. Сама семантика вызова и, в частности, контроль фактических параметров будут одинаковы в обоих случаях. Описание extern "C" имеет смысл использовать еще и потому, что языки С и С++, как и их реализации, близки друг другу. Отметим, что в описании extern "C" упоминание С относится к порядку связывания, а не к языку, и часто такое описание используют для связи с Фортраном или ассемблером. Эти языки в определенной степени подчиняются порядку связывания для С.       Утомительно добавлять "C" ко многим описаниям внешних, и есть возможность указать такую спецификацию сразу для группы описаний. Например:       extern "C" {       char* strcpy(char*, const char);       int strcmp(const char*, const char*)       int strlen(const char*)       // ...       }       В такую конструкцию можно включить весь заголовочный файл С, чтобы       указать, что он подчиняется связыванию для С++, например:       extern "C" {       #include <string.h>       }       Обычно с помощью такого приема из стандартного заголовочного файла       для С получают такой файл для С++. Возможно иное решение с       помощью условной трансляции:       #ifdef __cplusplus       extern "C" {       #endif       char* strcpy(char*, const char*);       int strcmp(const char*, const char*);       int strlen(const char*);       // ...       #ifdef __cplusplus       }       #endif       Предопределенное макроопределение __cplusplus нужно, чтобы обойти       конструкцию extern "C" { ...}, если заголовочный файл используется       для С.       Поскольку конструкция extern "C" { ... } влияет только на       порядок связывания, в ней может содержаться любое описание,       например:       extern "C" {       // произвольные описания       // например:       static int st;       int glob;       }       Никак не меняется класс памяти и область видимости       описываемых объектов, поэтому по-прежнему st подчиняется внутреннему       связыванию, а glob остается глобальной переменной.       Укажем еще раз, что описание extern "C" влияет только на       порядок связывания и не влияет на порядок вызова функции. В частности,       функция, описанная как extern "C", все равно подчиняется правилам       контроля типов и преобразования фактических параметров, которые в C++       строже, чем в С. Например:       extern "C" int f();       int g()       {       return f(1); // ошибка: параметров быть не должно       }