0

I have this from C++ primer 5th edition: External Linkage:

If one function among a set of overloaded functions is a C function, the other functions must all be C++ functions:

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 SmallInt&);
extern BigNum calc(const BigNum&);

The C version of calc can be called from C programs and from C++ programs. The additional functions are C++ functions with class parameters that can be called only from C++ programs. The order of the declarations is not significant.

  • So what I understood from these declarations is that I can put them in a header. e.g:

    // calc.h
    #ifdef __cplusplus
    
    class SmallInt { /* . . .   */ };
    class BigNum { /* . . .   */ };      
    
    // C++ functions can be overloaded
    extern SmallInt calc(const SmallInt&);
    extern BigNum calc(const BigNum&);
    extern "C" 
    
    #endif
    
    double calc(double); // C function
    
  • So do I need to define C version in a C source file and C++ version in a C++ source file?

    // calc.c
    #include "calc.h"
    
    double calc(double){} // do_something
    
    // calc.cxx
    #include "calc.h"
    
    SmallInt calc(const SmallInt&){} // do_something
    BigNum calc(const BigNum&){} // do_something
    
  • Now I need to compile this way:

     gcc print.c -c && g++ main.cxx print.cxx print.o -o prog
    
  • It works just fine but am I correct about my guesses and implementing this code?

  • What is the point in extern in the C++ versions (calc(const SmallInt&) and calc(const BigNum&)) as long as they cannot be compiled with a C compiler? Thank you so much!

Itachi Uchiwa
  • 3,044
  • 12
  • 26

2 Answers2

1

No, you can define all the functions in CPP source files, and call them from C (easily, if they are declared as having C linkage).

One source file, print.cxx, can have the implementation (function bodies) for all three functions. It is compiled as C++, and the implementation of double calc(double) can certainly use C++ to do its work.

A C program can be linked with that .o file, and call calc(double).

It can be useful to make C-callable API for a C++ library, and you can see that that must be part of the C++ source in order to work.

When you write extern "C", you are saying you will support calling that function from a C source file. It does not mean that the function is itself written in C.

JDługosz
  • 5,592
  • 3
  • 24
  • 45
  • 1
    *"and call them from C"* - All of them? You should polish that point a bit more. – StoryTeller - Unslander Monica Sep 09 '21 at 00:25
  • @StoryTeller-UnslanderMonica: So am I right (about the book examples)? if I have a set of overloaded functions then I can only mark one of them as a C function (linkage) thus I only can define that C version in a source file.c and the remaining overloads in a C++ file? So I can compile the C source with C or C++ compiler and only C++ source using a C++ compiler? – Itachi Uchiwa Sep 09 '21 at 21:27
  • 1
    @ItachiUchiwa - You don't need to compile to the source file with a C compiler. A C++ compiler will, do. And there can be both `extern "C"` and `extern "C++"` declaration in the source. What's important that any C code that includes your header, should only encounter C-friendly declaration. So the header you have is fine. Once you compiled your code, the resulting object file can be linked regardless of the source language. – StoryTeller - Unslander Monica Sep 09 '21 at 21:41
  • @StoryTeller-UnslanderMonica: One last thing: What is the point in `extern` in `calc(const SmallInt&)` and `calc(const BigNum&)`? Is it redundant? – Itachi Uchiwa Sep 09 '21 at 21:44
  • 1
    @ItachiUchiwa - Indeed redundant. I imagine somebody just considered it more pleasing on the eye, since the declarations sync more (in the number of characters) with the `extern "C"` one above. – StoryTeller - Unslander Monica Sep 09 '21 at 21:49
  • @StoryTeller-UnslanderMonica: Thank you so much always for your help and useful information. I am really so grateful. – Itachi Uchiwa Sep 09 '21 at 21:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/236954/discussion-between-itachi-uchiwa-and-storyteller-unslander-monica). – Itachi Uchiwa Sep 09 '21 at 21:54
0

When we talking about "C linkage", in fact we just care about header files. Making the function signature "extern C" in the header files is enough for foreign language (like rust/go) to call it.

And the so-called "C linkage" has a counterpart called "C++ linkage". The later has parameter types in the signature, but the former is just plain simple function name.

For example: compile this file:

// example.cpp
#include <array>
using namespace std;
extern "C"
double funcAlpha(double, int){
    return 0;
}

double funcBeta(double, int){
    return 0;
}

int main(){
}

run gcc example.cpp -o a.out && objdump -t a.out | grep func, you will get

000000000040046e g     F .text  000000000000001c              _Z8funcBetadi
0000000000400452 g     F .text  000000000000001c              funcAlpha

where d = double, i = int

Mike Dog
  • 74
  • 1
  • 6