Using extern to include files in C or C++ - c++

How this works in C or C++?
extern "C" {
#include <unistd.h>
#include <fd_config.h>
#include <ut_trace.h>
#include <sys/stat.h>
#include <sys/types.h>
}

The C++ standard does not specify how compilers should name the symbols in their object files (for instance, Foo::bar() might end up as __clsFoo_fncBar or some gobbledygook). The C standard does, and it is almost always different from how C++ compilers do it (C doesn't have to deal with classes, namespaces, overloading, etc.).
As a result, when you are linking against an object file that was output by a C compiler, you have to tell your C++ compiler to look for symbols with names that correspond to the C standard. You are essentially putting it in "C mode." This is what the "C" part of extern "C" does.
(Alternatively, you might also be declaring functions or variables that could be used by an external C object file. In this case, it means export those symbols the C way.)

If your Project has C and C++ source files and you need to build as a whole( C files calls some functions in C++ files) ,so we need to protect the C file function calls and symbols by declaring as in C++ files by
extern "C"
{
/symbols used in c files/
uint8 GetCurrentthreadState(HANDLE ThreadId)
}
Then the C++ complier generate compilation output which is same as that of C complier for the above declared functions and symbols.So on linking time , the compiler can easily link the C and C++ defined symbols with out any link error.
So my opinion is not needed to give the #ifdef __cplusplus check on compilation.
Because we need to protect the symbols in c++ files right? Also C++ files can be compiled by C++ compiler only right?
/renjith g

It will not work, you need to add the cplusplus preprocessor...
#ifdef __cplusplus
extern "C" {
#endif
// your code
#ifdef __cplusplus
}
#endif
EDIT:
In C++, the name will be treated like in C which mean that there will be no mangle name. It allows to make the difference between two C++ different function with different argument type/number or a different namespace in a library (for library purpose libname.so, libname.a). If the name is mangled, the C program will not be able to recognize it
eg:
int myfction()
void myfunction(int)
void myfunction(int, char)
C library: myfction
C++ library: int_myction (it depend on your compiler)
C++ library: int_myction_int (it depend on your compiler)
C++ library: int_myction_int_char (it depend on your compiler)
// ... which is not allowed in C program

Every C++ Compiler needs to support the extern "C" linkage.
The code in such block could be legacy code written in C for a certain functionality, which is required for the current program.
How this is implemented is mostly compiler dependent, However I heard that many Compilers disable the name mangling and change the calling convention.

Related

Linking to C libraries from C++: why isn't extern always needed?

Usually to get a C library working from C++ you have to include it with extern "C" { #include <clibrary.h> }. Many libraries will include in their header files code like #ifdef __cplusplus extern "C" { ... to make them more user friendly to C++ code (e.g. pthread.h). Sometimes this is not the case. For instance, stdio.h has no such #ifdef, yet I can still compile & link the usual #include <stdio.h> int main() {printf("Hello");} using a C++ compiler without wrapping it in an extern "C" statement. Why is this?
Usually to get a C library working from C++ you have to include it with extern "C" { #include <clibrary.h> }.
Only when the library was not designed with C++ compatibility in mind. But this is a hack.
Many libraries will include in their header files code like #ifdef __cplusplus extern "C" { ... to make them more user friendly to C++ code (e.g. pthread.h)
Yes, a good library will do this.
As a result, you do not need to and should not add another extern "C" around the #include.
stdio.h is an example of a header that will be doing this properly (see below).
For instance, stdio.h has no such #ifdef
Sure it does! Follow the money trail…
why isn't extern always needed?
So, in conclusion, you only need to do this yourself when the author of the header file didn't do it for you. When the author of the header file did it, you do not need to do it.
For instance, stdio.h has no such #ifdef
It probably does. Regardless, <stdio.h> is a header provided by the C++ standard library (inherited from the C standard library). It is guaranteed to work without extern "C" as are all standard headers.
Note that the usage of <name.h> name of the inherited standard headers in C++ instead of <cname> is deprecated in the current edition of the standard and has been identified as a candidate for removal in future revisions.
why isn't extern always needed?
Simply because some headers have been written to support C++ directly, and so do it by themselves.

In ref : Linking C compiled static library to C++ Program

Stackoverflow won't let me comment because I am a newbie.
Borrowing the title from the question posted here, the accepted solution says that you have to modify the C header file using #ifdef __cplusplus and extern "C".
I have the exact same question but I have been provided a C library containing over 100 .h C header files and .c C program files and now I have to use a C++ library so my main() will be in C++.
So do I now have to add those modifications to each one of those C header files or is there some other approach? My main() is in a .cpp file which will use functions from this C library.
EDIT
This question has been resolved. I wish for this question to be closed or removed.
You don't have to modify any headers. What is necessary is to wrap all C declarations with extern C {}. You can do this just as well in you cpp file:
extern "C" {
#include "some_c_header.h"
}
int main() {
std::cout << "This is C++ code\n";
}
It might be useful to create a header file which simply includes C headers with C linkage:
// c_header.hpp
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "c_header_1.h"
#include "c_header_2.h"
#ifdef __cplusplus
}
#endif
// main.cpp
#include "c_header.hpp" // extern "C" {} already handled for you
Only those declarations of C functions and objects that are accessed by C++ components need to declared with C linkage, and only to the C++ components. Presumably, your new C++ library accesses very little, if anything, from the existing C code, so the primary concern would be whatever is accessed (directly) by main(). Those functions must be declared (to main) with C linkage. If that turns out to be a significant number of things then you could consider refactoring to make it fewer.
Moreover, no, you do not need to modify existing header files. The C++ files that reference your C library, and that therefore include some of its headers, can wrap the relevant #include statements an an extern "C" block to take care of the issue.

Why could c++ include <stdio.h> and invoke printf method which is c(platform:ubuntu 14.04 compiler:gcc 4.8.4)

c++ compiler could compile code like this, and it executed correctly
#include <stdio.h>
int main() {
printf("test...\n");
return 0;
}
I think printf.c will be compiled to printf.o with c compiler, I just checked the stdio.h, there is no extern "C" keyword, then how could c++ linker link printf in printf.o which is compiled with c compiler?(By the way, my platform is ubuntu 14.04, compiler is gcc 4.8.4)
printf is part of the C++ standard library.
The <stdio.h> header that you include in the C++ source, belongs to the C++ standard library, and is not necessarily the same contents as a C compiler will include.
How the C++ implementation leverages the corresponding C implementation (if at all) is an implementation detail.
When C++ was originally made it was effectively a superset of C. That is to say, you can code perfectly good C in the C++ environment, just by ignoring all of the features that C++ adds. That, and because nowadays most C compilers are C++ compilers in which you can code C, is why you can use printf.
Secondly, no object code is generated for stdio because it is already a library, and so you are linking your own .o code against the already compiled stdio library code, which will be located somewhere in your compilers directory.
Nobody can give you a definitive answer without knowing what implementation you're using.
Cheers and hth. - Alf gave one possibility, which is that the stdio.h that is included by a C++ program may not be the same as the stdio.h that is included by a C program. Another possibility is that it is the same header, and there is an extern "C" block, and you just can't see it. For example, I use gcc, and my /usr/include/stdio.h contains a __BEGIN_DECLS macro, which expands to extern "C" { when compiled as C++. See Do I need an extern "C" block to include standard C headers?
You may not see an explicit extern "C" in stdio.h, but it is there. It's just hiding.
For example, on Linux, in stdio.h we see this:
#include <features.h>
__BEGIN_DECLS
In <features.h> you will find the following:
# ifndef _SYS_CDEFS_H
# include <sys/cdefs.h>
# endif
And in <sys/cdefs.h> you finally see:
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
So, via a fairly roundabout path, Linux header files have a __BEGIN_DECLS/__END_DECLS wrapper which, when compiled by a C++ compiler, end up wrapping the whole thing inside extern "C".

Compiling C as C++ linker error (lua and oolua)

I am having trouble with a piece of C code that is compiled as C++ producing a linker error from a 3rd package.
The setup is I have lua, oolua, and my program which utilizes the two. This project was moved from luabind due to its horrid build process. My code occasionally will throw an exception (which is expected) when constructing an object, and oolua does not handle this error.
From the reading I've done compiling lua as C++ should alleviate this problem and cause the program to not just quit, but the problem is oolua doesn't like lua being C++ for some reason and I cannot find references to why this could be.
tl;dr: If C code is compiled as C++ what problems could occur with linking assuming it compiles correctly?
When Lua is compiled as C++ it actually uses C++ name mangling and the normal headers should be used by C++. Don't be confused by the lua.hpp header. That should only be used for C++ when Lua is compiled as C. As a result when you compile Lua as C++ you should not use extern "C". Unfortunately OOLua does use extern "C" here. You could try modifying the header in OOLua to not use extern "C" and then recompile OOLua or file a bug with them to fix it properly.
Unfortunately not many people seem to be aware of the pitfalls of using Lua with C++ so many projects assume Lua is compiled as C as normal.
Long explanation:
When Lua is compiled as C there are no extern statements and therefore all functions get the default (extern "C"). When C files use Lua they use the normal header files which again contain no extern statements so the compiler presumes everything to be extern "C" and it all matches the library. If you use Lua from C++ you use lua.hpp which contains the extern "C" block so your compiler knows that Lua is extern "C".
When Lua is compiled as C++ there are no extern statements so the compiler assumes all functions in Lua are extern "C++". You can no longer use Lua directly from C. If you use Lua from C++ with the lua.hpp then it sees the extern "C" block, assumes Lua functions are extern "C" and fails at link time because of the wrong mangling. If you use the normal headers directly from C++ then there are no extern statements so extern "C++" is assumed. This matches the library and all is OK.
What OOLua does is it includes the normal headers but has it's own extern "C" around it so the compiler uses extern "C" linkage for all Lua functions when they are in fact using C++ linkage, the mangling is wrong and you get lots of linker errors about missing symbols.

extern "C" (C linkage) by default

Question
Do GCC, MSVC, or Clang, or some combination support setting linkage to default to C?
Background
I have a large mixed C/C++ project, and while it's easy and logical to export symbols in the C++ sources with C linkage, those same sources are assuming the stuff in the rest of the project are under C++ linkage.
The current situation requires me to explicitly wrap anything the C sources use that is defined in the C++ sources and everything the C++ sources use from the C sources with extern "C++".
To top things off, I can't put extern "C" around entire source or header files, as the actual C++ stuff will then complain. (Such as from #include <memory> or templates I've defined.)
The standard pattern in a header file is:
#ifdef __cplusplus
// C++ stuff
extern "C" {
#endif
// C/C++ stuff
#ifdef __cplusplus
}
#endif
I'm not sure you've got any other options. The C/C++ stuff must be declared with C linkage everywhere. The C++-specific stuff must be declared with C++ linkage everywhere.
"C" linkage by default makes only sense for C sources, not for C++ sources, and vice versa. "C" linkage usually implies that names/symbols will not be mangled. "C" linkage is not expressive enough to be usable for C++ sources, e.g. for overloaded functions.