Когда использовать экстерна “C” в простых словах? [дубликат]

Этот вопрос уже имеет ответ здесь:

Возможно, я не понимаю различий между C и C++, но когда и почему мы должны использовать

extern "C" {

? По-видимому, это - "конвенция связи".

Я читал об этом кратко и заметил, что все.h заголовочные файлы, включенные с MSVS, окружают свой код им. Какой код точно является "C кодом" и НЕ "кодом C++"? Я думал, что C++ включал весь код C?

Я предполагаю, что дело обстоит не так и что C++ отличается и что стандартные функции/функции существуют в одной или другой, но не оба (т.е.: printf является C, и судом является C++), но что C++ назад совместим хотя экстерн "C" объявление. Это корректно?

Мой следующий вопрос зависит от ответа на первое, но я спрошу это здесь так или иначе: Так как заголовочные файлы MSVS, которые записаны в C, окружаются экстерном "C" {...}, когда необходимо было бы когда-либо использовать это сами в собственном коде? Если Ваш код является кодом C, и Вы пытаетесь скомпилировать его в компиляторе C++, разве он не должен работать без проблемы, потому что весь стандарт h файлы, которые Вы включаете, будет уже иметь экстерна "C" вещью в них с компилятором C++?

Необходимо ли использовать это при компиляции в C++, но соединении с уже созданными библиотеками C или чем-то?

26
задан Jonathan Leffler 4 June 2016 в 04:52
поделиться

7 ответов

extern "C" {} блоки сообщают компилятору C++ использовать соглашения об именовании и вызове C. Если вы не используете это, вы получите ошибки компоновщика при попытке включить библиотеку C в свой проект C++, потому что C++ будет искажать имена.Я склонен использовать это на всех своих заголовках C на случай, если они когда-либо будут использоваться в проекте C++:

#ifdef __cplusplus
extern "C" {
#endif

/* My library header */

#ifdef __cplusplus
} // extern
#endif
2
ответ дан 28 November 2019 в 06:33
поделиться

Я использую 'extern c', чтобы C# мог читать мой код C++, не выясняя, как искажается лишнее имя при экспорте функции C++ dll. В противном случае есть дополнительные бессмысленные (или, на самом деле, неанглийские) символы, которые мне придется добавить в конце точки входа функции на стороне C#, чтобы правильно получить доступ к функции C++ в библиотеке DLL.

2
ответ дан 28 November 2019 в 06:33
поделиться

Вам нужно использовать extern «C» , если вы хотите использовать соглашение о вызовах C в коде, скомпилированном компилятором C ++. Для этого есть две причины:

  • У вас есть функция, реализованная на C, и вы хотите вызвать ее из C ++.

  • У вас есть функция, реализованная на C ++, и вы хотите вызвать ее из C. Обратите внимание, что в этом случае вы можете использовать только часть C C ++ в интерфейсе функции (без классов, ...).

Помимо C, это также применимо, когда вы хотите взаимодействовать между C ++ и другими языками, которые используют те же соглашения о вызовах и именах, что и C.

Обычно объявления в заголовочном файле C заключаются в

#ifdef __cplusplus
extern "C" {
#endif

[... C declarations ...]

#ifdef __cplusplus
}
#endif

, чтобы сделать его можно использовать с C ++.

2
ответ дан 28 November 2019 в 06:33
поделиться

Функции C++ подвержены искажению имен. Это делает невозможным их вызов непосредственно из кода на Си, если только не используется extern "C".

0
ответ дан 28 November 2019 в 06:33
поделиться

Вам необходимо использовать extern "C" в C ++ при объявлении функции, которая была реализована / скомпилирована на C. Использование extern "C" сообщает компилятору / компоновщику использовать соглашения об именах и вызовах C вместо преобразования имен C ++ и соглашений о вызовах C ++, которые использовались бы в противном случае. Для функций, предоставляемых другими библиотеками, вам почти никогда не понадобится использовать extern «C» , так как в хорошо написанных библиотеках это уже есть для общедоступных API, которые он экспортирует как на C, так и на C ++. Однако, если вы пишете библиотеку, которую хотите сделать доступной как на C, так и на C ++, вам придется условно поместить ее в свои заголовки.

Что касается того, является ли весь код C кодом C ++ ... нет, это неверно. Это популярный миф о том, что C ++ - это «надмножество C». Хотя C ++ определенно стремится быть максимально совместимым с C, есть некоторые несовместимости . Например, bool допустимый C ++, но недействительный C, тогда как _Bool существует в C99, но недоступен в C ++.

Что касается того, понадобится ли вам когда-нибудь использовать extern «C» с системными файлами «.h» ... любая хорошо спроектированная реализация будет иметь их там для вас, так что вам не нужно их использовать .Однако, чтобы быть уверенным, что они предоставлены, вы должны включить эквивалентный файл заголовка, который начинается с «c» и опускает «.h». Например, если вы включите , почти в любой разумной системе будет добавлен extern «C»; однако, чтобы быть уверенным, что заголовок совместим с C ++, вы должны вместо этого включить заголовок .

Вас также может заинтересовать Смешивание C и C ++ из C ++ FAQ Lite .

30
ответ дан 28 November 2019 в 06:33
поделиться

Компиляторы C ++ изменяют имена в своей таблице символов иначе, чем компиляторы C. Вам нужно использовать объявление extern "C" , чтобы указать компилятору C ++ использовать соглашение об изменении языка C при построении таблицы символов.

13
ответ дан 28 November 2019 в 06:33
поделиться

Другие ответы верны, но полный пример "boilerplate", вероятно, поможет. Канонический метод включения C-кода в проекты на C и/или C++ выглядит следующим образом:

//
// C_library.h
//

#ifdef __cplusplus
extern "C" {
#endif

//
// ... prototypes for C_library go here ...
//

#ifdef __cplusplus
}
#endif

-

//
// C_library.c
//

#include "C_library.h"

//
// ... implementations for C_library go here ...
//

-

//
// C++_code.cpp
//

#include "C_library.h"
#include "C++_code.h"

//
// ... C++_code implementation here may call C functions in C_library.c ...
//

Примечание: вышесказанное относится и к вызову C-кода из Objective-C++.

17
ответ дан 28 November 2019 в 06:33
поделиться