I'm writing a C library, which may potentially be useful to people writing C++. It has a header which looks like this:
#ifndef FOO_H_
#define FOO_H_
#include <bar.h>
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void foo_func();
#ifdef __cplusplus
}
#endif
#endif
and I was wondering - should I move the extern "C" bit before including the header include directives? Especially seeing how, in practice, some of those headers might themselves have an extern "C"?
NO, in general you shouldn't move it to include the headers.
extern "C"is used to indicate that the functions is using the C calling convention. The declaration has no effect on variables and#defines, so there is no need to include these. If an#includeis inside anextern "C"block, this effectively modifies the function declarations inside that header file!Background: Without the
extern "C"declaration, when compiling using a C compiler, a function is assumed to follow the C convention, and when compiling using a C++ compiler, the C++ convention is assumed. In case the same header file is used for C and C++ code, you would get a linker error, since the compiled function has different names in C and C++.Although it's possible to put all your code between the #ifdef blocks, I personally don't like it, because it's really only intended for the function prototypes, and I frequently see people copy-pasting this at places where it shouldn't be. The cleanest way is to keep it where it's supposed to be, which is around the function prototypes in a C/C++ header file.
So, to answer your question "should I move the
extern "C"bit before including the header include directives?", my answer is: No, you shouldn't.But is it possible? Yes, and in many cases this won't break anything. Sometimes it is even necessary, if the function prototypes in an external header file are incorrect (e.g. when they are C functions and you want to call them from C++) and you cannot change that library.
However, there are also cases where doing so breaks the build. Here's a simple example that fails to compile if you wrap the include using
extern "C":foo.h:
foo.c:
bar.h:
bar.cpp:
main.cpp:
When uncommenting the blocks in a.h, I get the following error:
Without, it builds fine. A C main calling only C functions from foo and bar will build fine either way, since it's unaffected by the
#ifdef __cplusplusblocks.