Is extern "C" only required on the function declaration?

22,368

Solution 1

The 'extern "C"' should not be required on the function defintion as long as the declaration has it and is already seen in the compilation of the definition. The standard specifically states (7.5/5 Linkage specifications):

A function can be declared without a linkage specification after an explicit linkage specification has been seen; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration.

However, I generally do put the 'extern "C"' on the definition as well, because it is in fact a function with extern "C" linkage. A lot of people hate when unnecessary, redundant stuff is on declarations (like putting virtual on method overrides), but I'm not one of them.

Solution 2

Just encountered this situation... Not a pleasant experience.

The following was declared in one of my c files:

void unused_isr(void) {}
void ADC_IRQHandler(void)     __attribute__ ((weak, alias("unused_isr"))); 

Next somewhere in a cpp file I defined:

void ADC_IRQHandler(void) {                                                                                  
    ...
}

And I forgot to change the forward declaration to:

void ADC_IRQHandler(void);

It took me a while before I figured out I was doing everything right with respect to the AD conversion, but I failed to add "extern C" to the definition!

extern "C" void ADC_IRQHandler(void) {                                                                                  
    ...
}

Just my two cents why it might be useful in certain circumstances to have the habit to add it to the definition as well.

Solution 3

I think this needs to be clarified here, as I just had a similar issue and it took me a while to get this clear in my head, only Brooks Moses touched on this properly, and I think it needs to be stated more clearly ...

In summary the header may throw you off, all the compiler sees is the cpp file and if the header is not included with the extern "C" back into your cpp (which I commonly see), then the extern "C" will need to be in the cpp file somewhere (either in the definition, or another declaration) so the CXX compiler can know to make it with C linkage, the compiler does not care about the header, only the linker.

Solution 4

Edit:
Seems like I had misunderstood the question. Anyways, I tried:


// foo.cpp
/* Function definition */

#include "foo.h"

void foo(int i) {
 //do stuff
}
void test(int i)
{
// do stuff
}

// foo.h
#ifdef __cplusplus
extern "C" {
#endif

/* Function declaration */
void foo(int);

#ifdef __cplusplus
}
#endif

void test(int);

Using command nm to view the symbols from the compiled file:


linuxuser$ nm foo.o
00000006 T _Z4testi
         U __gxx_personality_v0
00000000 T foo

This clearly suggests that the name of function declared as extern "C" is not mangled and the extern "C" keyword is not required at definition.
Had it required every C library code written without extern "C" would have been unusable in C++ programs.

Share:
22,368
bporter
Author by

bporter

Updated on September 24, 2020

Comments

  • bporter
    bporter over 3 years

    I wrote a C++ function that I need to call from a C program. To make it callable from C, I specified extern "C" on the function declaration. I then compiled the C++ code, but the compiler (Dignus Systems/C++) generated a mangled name for the function. So, it apparently did not honor the extern "C".

    To resolve this, I added extern "C" to the function definition. After this, the compiler generated a function name that is callable from C.

    Technically, the extern "C" only needs to be specified on the function declaration. Is this right? (The C++ FAQ has a good example of this.) Should you also specify it on the function definition?

    Here's an example to demonstrate this:

    /* ---------- */
    /* "foo.h"    */
    /* ---------- */
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /* Function declaration */
    void foo(int);
    
    #ifdef __cplusplus
    }
    #endif
    
    /* ---------- */
    /* "foo.cpp"  */
    /* ---------- */
    
    #include "foo.h"
    
    /* Function definition */
    extern "C"               // <---- Is this needed?
    void foo(int i) {
      // do something...
    }
    

    My issue may be the result of incorrectly coding something, or I may have found a compiler bug. In any case, I wanted to consult stackoverflow to make sure I know which is technically the "right" way.

  • Brooks Moses
    Brooks Moses over 14 years
    This is incorrect in the case as described, where foo.h is included in foo.c, and "get away with" is misleading for using behavior required by the standard. If one includes foo.h in foo.c -- as one should always be doing anyway, so that the compiler can check that the declaration is actually accurate! -- then there is no need (other than perhaps clarity to readers) -- to put extern "C" on the definition within foo.c.
  • bporter
    bporter over 14 years
    @Neeraj - Thanks for your example. This is what I expected to see in my case as well. It appears my compiler mangles the "foo" function name unless I specify 'extern "C"' on the declaration and the definition. I think you and some of the other posters are correct that the 'extern "C"' is not required on the definition as long as it is specified on a previous declaration.
  • bporter
    bporter over 14 years
    @Michael Burr - Thanks for your response. It sounds like the 'extern "C"' is not required on the definition as long as it is specified on a previous declaration. Like you mentioned, I may go ahead and specify it in both places, however. (In fact, I may need to unless I figure out that my problem is something other than a compiler bug. If it does look like a compiler bug, then I'll report it to the vendor so they can look into it.)
  • Mawg says reinstate Monica
    Mawg says reinstate Monica about 7 years
    I thought that I was the only one who puts virtual on method overrides :-)