Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Cpp_Страуструп.doc
Скачиваний:
16
Добавлен:
03.05.2015
Размер:
3.2 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); // ошибка: параметров быть не должно

}