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?
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With