#c #c #overloading #external-links
Вопрос:
У меня есть это из 5-го издания C primer: Внешняя связь:
Если одна функция из набора перегруженных функций является функцией C, все остальные функции должны быть функциями C :
class SmallInt { /* . . . */ }; class BigNum { /* . . . */ }; // the C function can be called from C and C programs // the C functions overload that function and are callable from C extern "C" double calc(double); extern SmallInt calc(const SmallIntamp;); extern BigNum calc(const BigNumamp;);
Версию C
calc
можно вызвать из программ на C и из программ на C . Дополнительными функциями являются функции C с параметрами класса, которые могут вызываться только из программ на C . Порядок деклараций не имеет значения.
- Итак, что я понял из этих заявлений, так это то, что я могу поместить их в заголовок. например:
// calc.h #ifdef __cplusplus class SmallInt { /* . . . */ }; class BigNum { /* . . . */ }; // C functions can be overloaded extern SmallInt calc(const SmallIntamp;); extern BigNum calc(const BigNumamp;); extern "C" #endif double calc(double); // C function
- Итак, нужно ли мне определять версию C в исходном файле C и версию C в исходном файле C ?
// calc.c #include "calc.h" double calc(double){} // do_something // calc.cxx #include "calc.h" SmallInt calc(const SmallIntamp;){} // do_something BigNum calc(const BigNumamp;){} // do_something
- Теперь мне нужно скомпилировать этот способ:
gcc print.c -c amp;amp; g main.cxx print.cxx print.o -o prog
- Это работает просто отлично, но прав ли я в своих догадках и реализации этого кода?
- Какой смысл
extern
в версиях C (calc(const SmallIntamp;)
иcalc(const BigNumamp;)
), если они не могут быть скомпилированы с помощью компилятора C? Большое вам спасибо!
Ответ №1:
Нет, вы можете определить все функции в исходных файлах CPP и вызвать их из C (легко, если они объявлены как имеющие связь C).
Один исходный файл, print.cxx
, может иметь реализацию (тела функций) для всех трех функций. Он скомпилирован как C , и реализация double calc(double)
, безусловно, может использовать C для выполнения своей работы.
Программа на языке Си может быть связана с этим .o
файлом и вызвать calc(double)
.
Может быть полезно создать C-вызываемый API для библиотеки C , и вы можете видеть, что это должно быть частью исходного кода C , чтобы работать.
Когда вы пишете extern "C"
, вы говорите, что будете поддерживать вызов этой функции из исходного файла на языке C. Это не означает, что сама функция написана на C.
Комментарии:
1. «и позвонить им из» С » — всем им? Вам следует еще немного отполировать этот момент.
2. @StoryTeller-UnslanderMonica: Так я прав (о примерах из книг)? если у меня есть набор перегруженных функций, я могу пометить только одну из них как функцию C (связь), поэтому я могу определить только эту версию C в исходном файле.c, а остальные перегрузки в файле C ? Таким образом, я могу скомпилировать источник C с помощью компилятора C или C и только источник C с использованием компилятора C ?
3. @ItachiUchiwa — Вам не нужно компилировать исходный файл с помощью компилятора Си. Компилятор C подойдет. И в источнике может быть как
extern "C"
иextern "C "
объявление, так и объявление. Что важно, так это то, что любой код C, включающий ваш заголовок, должен встречаться только с объявлением, дружественным к C. Так что заголовок, который у вас есть, в порядке. После того, как вы скомпилировали свой код, полученный объектный файл может быть связан независимо от исходного языка.4. @Рассказчик-UnslanderMonica: И последнее: Какой смысл
extern
вcalc(const SmallIntamp;)
иcalc(const BigNumamp;)
? Это лишнее?5. @Итачиучива — Действительно излишне. Я предполагаю, что кто-то просто счел это более приятным для глаз, так как объявления больше синхронизируются (по количеству символов) с приведенным
extern "C"
выше.
Ответ №2:
Когда мы говорим о «связывании C», на самом деле мы просто заботимся о файлах заголовков. Для вызова функции на иностранном языке (например, rust/go) достаточно указать сигнатуру функции «extern C» в заголовочных файлах.
И так называемая «связь C» имеет аналог, называемый «связь C «. В последней подписи есть типы параметров, но первая — это просто простое имя функции.
Например: скомпилируйте этот файл:
// example.cpp
#include <array>
using namespace std;
extern "C"
double funcAlpha(double, int){
return 0;
}
double funcBeta(double, int){
return 0;
}
int main(){
}
беги gcc example.cpp -o a.out amp;amp; objdump -t a.out | grep func
, ты получишь
000000000040046e g F .text 000000000000001c _Z8funcBetadi
0000000000400452 g F .text 000000000000001c funcAlpha
где d = двойной, i = int