Подтвердить что ты не робот

Должна ли внешняя "C" включать объявление или определение функции С++?

Я видел в файле cpp, что external "C" {...} содержит определения нескольких функций.

Из https://isocpp.org/wiki/faq/mixing-c-and-cpp я предполагаю, что цель использования extern "C" в файле cpp - сделать закрытые функции С++ доступными для использования в программе C,

Пример в ссылке показывает, что extern "C" содержит только объявления функций С++, а не их определения

Просто объявите функцию С++ extern "C" (в коде С++) и вызовите он (из вашего кода C или С++). Например:

    // C++ code:
    extern "C" void f(int);
    void f(int i)
    {
        // ...
    }

Файл cpp, о котором я упоминал в начале, выглядит следующим образом:

    // C++ code:
    extern "C" {

    void f(int i)
    {
        // ...
    }

    void g(int i)
    {
        // ...
    }

    }

Скрыть extern "C" заключить объявления или определения функций С++? Если да, то почему?

4b9b3361

Ответ 1

Он должен заключать объявления в файл заголовка, и определения должны быть заключены так долго, пока блок перевода скомпилирован с использованием компилятора С++, и пока декларация там не была видна.
Это никогда не ошибочно делает оба в коде С++.

Если компилятор c используется для компиляции определений функций, он не нужен (или лучше сказать, будет неправильный синтаксис, см. примечание ниже).

extern "C" {} Управляет областью, в которой используется простая связь символов c. В противном случае будет применено С++ name mangling.


Примечание:

Так как extern "C" {} это недопустимый синтаксис c, чтобы сделать это с компилятором c, вам нужно использовать его в #ifdef:

MyHeader.h:

 #ifdef __cplusplus
 extern "C" {
 #endif

 // ... c style function name declarations
 void foo(int i);

 #ifdef __cplusplus
 } // extern "C"
 #endif

Использование области extern "C" {} фактически двоякое:


Экспорт кода С++ в C

Если приведенное выше скомпилировано с помощью компилятора c, оно появляется для него как декларация функции c. Если скомпилировано с компилятором С++, применяется ключевое слово extern, и сглаживание имени С++ будет подавлено.

В отношении определения функция может использовать любые встроенные в нее функции С++:

 extern "C" {
     void foo(int x) {
         std::vector v(x);
         // ... blah, more c++ stuff
     }
 }

Обратите внимание, что объявление здесь не было включено. Это можно использовать в качестве метода, особенно полезно, когда вы хотите переопределить функции, открытые из библиотеки для слабой связи.

В случае включения MyHeader.h область extern "C" {} может быть опущена.


Импорт кода C из С++

Если приведенное выше объявление рассматривается в компиляторе С++, снова отменяется сглаживание имени С++, и любая ссылка на вызов foo() будет разрешена компоновщиком с использованием имени символа функции c:

  #include "MyHeader.h"
  class MyClass {
  public:
       void bar(int y) {
           // Use foo() as plain c function:
           foo(y);
       }
  };

Реализация функции foo() предоставляется из объектного файла (или архива), созданного с помощью компилятора c.

Ответ 2

[dcl.link]/5:

За исключением функций с С++-связью, объявление функции без спецификация связи не должна предшествовать первой привязке спецификации для этой функции. Функция может быть объявлена ​​без спецификации связи после того, как спецификация явной привязки была видели; ссылка, явно указанная в предыдущей декларации, не затрагивается таким объявлением функции.

Обе версии отлично подходят для языковой привязки функции. Важная часть состоит в том, что первое объявление функции должно иметь extern "C".

Ответ 3

Лучше должны включать оба.

Чтобы убедиться, что символ не искажен, когда мы связываем код C на С++. мы используем extern блок "C".

Всякий раз, когда какой-либо код помещается в блок extern "C", компилятор С++ гарантирует, что имена функций не отображаются. i.e компилятор сгенерирует двоичный файл с именами без изменений, как это сделает компилятор C.

Mangling Поскольку С++ поддерживает перегрузку функций, в принципе может быть более одной функции с тем же именем. Таким образом, чтобы различать различные функции при генерации объектного кода, он изменяет имена, добавляя информацию о аргументах. Техника добавления дополнительной информации к именам функций называется Name Mangling.

Поскольку C не поддерживает перегрузку функции. Поэтому мы используем блок extern 'C' при связывании кода C на С++.

Ответ 4

Вы должны приложить как декларации, так и определения. Функции "C" и "С++" экспортируются с разными именами. Для создания правильного "C" внешнего имени в объектном файле extern "C" требуется в cpp, иначе функция будет экспортироваться с С++ name mangling. Вы также должны заключить те extern "C" { и соответствующие } в #ifdef __cplusplus и #endif в заголовочный файл, который будет # включен в проект C, чтобы избежать ошибки компиляции C

Ответ 5

В тот же документ он показывает пример кода, который имеет extern "C" в объявлении, но не в определении.

Если ваше определение "видит" объявление (т.е. объявление предшествует определению в блоке перевода), вам не нужно extern "C" в определении. Но это не повредит - он будет игнорироваться компилятором.

Вот пример кода, приведенный в FAQ:

// This is C++ code
// Declare f(int,char,float) using extern "C":
extern "C" void f(int i, char c, float x);
// ...
// Define f(int,char,float) in some C++ module:
void f(int i, char c, float x)
{
  // ...
}

Если по какой-либо причине вы решите не включать объявление перед определением, вам необходимо предоставить модификатор extern "C":

// This is C++ code
// Define f(int,char,float) in some C++ module:
extern "C" void f(int i, char c, float x)
{
  // ...
}

Однако это противоречит большинству руководств стиля C и С++.