Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare an extern C function inside a function in C++?

Tags:

c++

c

I have an inline function, roughly like this:

inline void SomeFunction() {
    extern void SomeOtherFunction();
    SomeOtherFunction();
}

This is a simplification: my functions do have parameters and return values.

However, I want this header to work in both C and C++ files. Currently, linking fails because C++ files attempt to find an implementation of SomeOtherFunction with C++ linkage. I thought I could just fix this by using extern "C":

inline void SomeFunction() {
#ifdef __cplusplus
    extern "C" void SomeOtherFunction();
#else
    extern void SomeOtherFunction();
#endif
    SomeOtherFunction();
}

This causes Clang to fail with:

error: expected unqualified-id
    extern "C" void SomeOtherFunction();
           ^

How can I do this correctly?

like image 359
wham3 Avatar asked Jan 24 '26 14:01

wham3


2 Answers

extern "C" is a linkage-specification. C++ standard section 7.5 Linkage specifications paragraph 4 states that:

A linkage-specification shall occur only in namespace scope (3.3).

E.g. you can say extern "C" in global namespace or some specific namespace. Outside of namespaces it is illegal.

Function declarations are possible though in smaller scopes. If you remove linkage specification your code will compile (but not link):

inline void SomeFunction() {
    extern void SomeOtherFunction();
    SomeOtherFunction();
}

If you really need SomeOtherFunction declaration in a smaller scope (e.g. hide from global scope) you can put your declaration into a header file to a dedicated scope and then use in your function:

Header:

namespace other {
    extern "C" void SomeOtherFunction();
}//namespace other

Code:

void SomeFunction()
{
    other::SomeOtherFunction();
}

Credit goes to these two answers on stackoverflow: here and here.

like image 177
fukanchik Avatar answered Jan 27 '26 03:01

fukanchik


From the C++11 standard (in [dcl.link], emphasis mine):

4 Linkage specifications nest. When linkage specifications nest, the innermost one determines the language linkage. A linkage specification does not establish a scope. A linkage-specification shall occur only in namespace scope.

(linkage-specification refers to extern string-literal ..., i.e. extern "C" in your case.)

This means you can't have extern "C" inside of a class or function.

What's the point of declaring SomeOtherFunction inside of SomeFunction? It still has to be a global symbol and visible to the linker.

So why not do this?

#ifdef __cplusplus
    extern "C" 
#endif
void SomeOtherFunction();

inline void SomeFunction() {
    SomeOtherFunction();
}

The following also seems to work:

extern "C" {
    inline void SomeFunction() {
        extern void SomeOtherFunction();
        SomeOtherFunction();
    }    
}

But it would have the side effect of making SomeFunction also use C linkage (which is hopefully OK as (per your requirements) it needs to be usable from C, too).

like image 39
melpomene Avatar answered Jan 27 '26 04:01

melpomene



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!