I just got some C code that uses extern "C" to declare external functions like this:
extern "C" void func();
Is this valid C? I'm getting an error at this line, but I'm not sure if it's because of this or something else.
No, it's not valid C. It should only be used in C++ code to refer to functions defined in C code. The extern "C" should be surrounded in a ifdef __cplusplus/#endif block:
// For one function
#ifdef __cplusplus
extern "C"
#endif
void func();
// For more than one function
#ifdef __cplusplus
extern "C"
{
#endif
void func1();
void func2();
#ifdef __cplusplus
}
#endif
this is a C++ notation to tell the compiler/linker to use C calling standards.
Usually that line is wrapped in an pre-processor statement.
#ifdef __cplusplus
extern "C" {
#endif
// stuff
#ifdef __cplusplus
}
#endif
Not valid in C. If present after preprocessing this will result in a diagnostic as per the standard.
For C++, this turns of name-mangling. See this for more details as to why it may be required. Can you post some more details?
Related
I have a .cpp file which I declare a function
#ifndef MyFile_hpp
#define MyFile_hpp
#ifdef __cplusplus
extern "C" {
#endif
void runCode();
#ifdef __cplusplus
}
#endif
#endif
This works fine. I can call this function within my Objc. In my implementation I have an extern void that it will not let me call. It's giving the undefined symbols. I need this to build as is, the extern will be declared in a different file upon compiling. Having the extern, should this compiler just trust me and let me build?
#include "MyFile.h"
extern int runMe();
#ifdef __cplusplus
extern "C" {
#endif
void runCode() {
runMe();
}
#ifdef __cplusplus
}
#endif
I think what you are doing is probably correct.
The compiler doesn't just trust you. A C++ function is declared to the linker using additional characters, or "decorations" that define the full detail of the cclass it is a member of and all its arguments. A C function has none of that, just the raw name, so it is easy for the linker to tell the difference.
I have some C code being called from C++.
The header resembles the following:
#ifndef CLibH
#define CLibH
#ifdef __cplusplus
extern "C" {
#endif
//C API
void foo(void);
// ...
#ifdef __cplusplus
}
#endif
#endif
Since I'm already using extern C,
is there any benefit to adding the nothrow compiler attribute?
#ifndef CLibH
#define CLibH
#ifdef __cplusplus
extern "C" {
#endif
//C API
void foo(void) __attribute__((nothrow));
// ...
#ifdef __cplusplus
}
#endif
#endif
Does extern C make this redundant?
Are there still advantages to applying it under these circumstances?
Yes, it does. From gcc documentation:
For example, most functions in the standard C library can be
guaranteed not to throw an exception with the notable exceptions of
qsort and bsearch that take function pointer arguments.
I have a header that I want to include from .c and .cpp files.
so I know about name mangling and extern "C" so...
#ifdef __cplusplus
extern "C"
{
int isPrime(int64_t p);
}
#endif
but when I include this in the .c file it doesn't see the function because of the #ifdef __cplusplus
so then I end up making 2 copies:
#ifdef __cplusplus
extern "C"
{
int isPrime(int64_t p);
}
#else
int isPrime(int64_t p);
#endif
is there a better way to do this... I thought about making another header called prototypes.h and including that in those 2 places... but is there something simple I am missing?
Yes, there is a better way. People are usually doing this :
#ifdef __cplusplus
extern "C"
{
#endif
int isPrime(int64_t p);
#ifdef __cplusplus
}
#endif
If you want to do something different in c and c++ (like for example this) then you can use the 2nd syntax in your question.
Another way of doing this is as follows
// intro
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
// content
EXTERN_C int isPrime(int64_t p);
// many other functions declared with EXTERN_C
Normally the "intro" part is placed in some common header file for everyone to use.
The advantage of this format is that each declaration is immediately seen as extern "C". A reader doesn't have to search around for possible extern "C" {
#ifdef __cplusplus
extern "C"
{
#endif
int isPrime(int64_t p);
#ifdef __cplusplus
}
#endif
That way, you can extend the int isPrime(int64_t p); part arbitrarily without repeating it in your #ifdef and #else cases.
I have these two namespaces, each one containing a function with the same name, like
namespace group1 {
void add(int arg) {
}
}
namespace group2 {
void add(bool arg) {
}
}
and I specify this in the header with the declarations
#ifdef __cplusplus
extern "C" {
#endif
// My namespaces and functions prototypes here
#ifdef __cplusplus
}
#endif
and I am trying to export them into a DLL, with GCC. I get a warning about a conflict between them because they have the same name, then an error at linking time. I thought the name was mangled in the object file based on the arguments, too. I don't know if the linker cares about the namespace too. How could I make this work? Thanks.
If these are C++ functions, you have to remove the extern "C" bracketing:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
extern "C" tells the compiler "don't mangle this name"--but (as you say) you want the mangling.
You can't really do that directly. When you use the extern "C", you are declaring that the functions are exported as if they were C functions, not C++.
This means (among other things)
Namespaces are removed, and are not considered part of the name
No name mangling due to arguments is done
The best you can do is create extern "C" functions which redirect.
#ifdef __cplusplus
extern "C" {
#endif
void group1_add(int arg);
void group2_add(bool arg);
#ifdef __cplusplus
}
#endif
And the implementations of the wrapper functions would then use either group1::add() or group2::add() as appropriate.
This question already has answers here:
What is the effect of extern "C" in C++?
(17 answers)
Closed 6 years ago.
I see some code in C++ using extern "C" at the beginning of the file like this:
#ifdef __cplusplus
extern "C" {}
#endif
What does this mean? How does it work?
It is used to inform the compiler to disable C++ name mangling for the functions defined within the braces. http://en.wikipedia.org/wiki/Name_mangling
It's probably not like that, but more like:
#ifdef __cplusplus
extern "C" {
#endif
//some includes or declarations
#ifdef __cplusplus
}
#endif
It tells the compiler to use C name mangling for whatever is declared inside the directives.
The way you have it now:
#ifdef __cplusplus
extern "C" {}
#endif
is just dead code.
Extern "C" - notify the compiler,that the noted function is compiled in C style.
It specifies a linkage specification.
It tells the linker how to link the code.
It is useful when you want to mix C and C++ code.