I have a C library that I need to use in a C++ code, so I need to wrap the whole lib with an extern "C" block. The problem is that the library seems to include a C++ compiled code, so wrapping the whole lib would also wrap that C++ header.
Inside lib.h I only include all the internal headers I want to expose, something like this:
#ifndef LIB_H
#define LIB_H
#include "lib_foo.h"
#include "lib_bar.h"
#include "lib_baz.h"
#endif
So the client will only need to include lib.h to use the lib.
In my first attempt I've done this:
#ifndef LIB_H
#define LIB_H
extern "C" {
#include "lib_foo.h"
#include "lib_bar.h"
#include "lib_baz.h"
}
#endif
But then I get a symbol lookup error when I execute any function inside already_compiled_c++.h.
How can I avoid from applying extern "C" in the already_compiled_c++.h header file?
Edit:
Solved. This was not a problem using extern "C", it was a problem linking the compiled c++ library with gyp correctly: Using shared library in Gyp in node-sqlite3
Note that extern C isn't legal C, so it must only be included hen compiling as C++.
The already_compiled_c++.h header probably contains a guard against multiple includes, so just include it first:
#ifndef LIB_H
#define LIB_H
# This include added so that it won't get marked extern "C" when included by lob_foo.h.
#include <already_compiled_c++.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_foo.h"
#include "lib_bar.h"
#include "lib_baz.h"
#ifdef __cplusplus
}
#endif
#endif
Note: You need to check if already_compiled_c++.h is conditionally included and add the corresponding conditionals.
You cannot call C++ from a file compiled in plain C.
If lib_foo.h is plain C, it cannot directly use the functions in already_compiled_c++.h. You will most likely need to create a C wrapper for it.
This answer may help you further: Elegantly call C++ from C
If your diagram is accurate, then lib_foo.h should not be including already_compiled_c++.h. Edit it to stop including that.
If the functions declared in already_compiled_c++.h had their implementation compiled to use the C++ ABI, there is no way that your C program could link against them. (short of extremely ugly hacking).
To avoid snarls like this in the future, explicitly put #ifdef __cplusplus extern "C" { guards in every header file which will have a C implementation, but might be used in a C++ program, and vice versa.
A workaround for your current situation would be to make a .cpp file that has thunks for the functions you need. Publish your thunks under extern "C", and implement them by calling the functions in already_compiled_c++.h.
Rethink your design. You can't include C++ headers from C, only the reverse. A few suggestions:
1) Although the original idea behind 'extern "C"' was to wrap includes of C headers from C++ files, if you have headers that should be C-accessible but are implemented in C++, the common approach is to wrap the declarations in it and not the includes. (With the requisite #ifdef __cplusplus so the C code, which always treats headers as being C, doesn't choke on the unneeded C++-ism 'extern "C"')
2) Don't expose C++ as the public API of a library. C++ in general does not provide a binary stable ABI. If you add a method and it's not at the end, or if you add an instance variable to a class, or if you change something in a templated class, all clients would have to be recompiled (with static libraries that usually happens anyway, but this is a big problem for dylibs/DLLs/frameworks). So in general the best idea is to keep C++ as an implementation detail and only expose C features from your library.
3) If you need to expose C++ from your library, use the Pimpl (private implementation) pattern and no templates, and put it in a separate header that isn't included by the master C header, so C clients can just not include it. Such a separate header is also useful for #2 because your library's modules' implementation files (which are in C++) can include it and thus use the classes in it.
4) To C++, a pointer to a struct Foo and a pointer to a class Foo are the same thing. So if you need to return a C++ class from a C-only API implemented behind the scenes in C++, what you can do is just always use struct Foo* in the headers (which C understands correctly), and provide C wrapper functions for the class's methods like:
extern "C" int FooGetCount( struct Foo* thisFoo )
{
return thisFoo->GetCount();
}
That way they can keep around pointers to C++ objects and access their properties, but don't need to actually use C++. Of course you also need to provide similar wrappers for creating/deleting the object, as C doesn't have the new/delete operators.
Related
I have a few questions about calling C standard library functions in C++:
If I want to call getline() which is declared in <stdio.h> is it always sufficient to just include <cstdio>? This works with the compiler I'm using and I see that it includes <stdio.h> in <cstdio> but I want to know if the standard guarantees this.
Are all C standard library functions guaranteed to be available in C++? With the getline() example from above I noticed that on cppreference under <cstdio> it doesn't list getline().
For C standard library functions and types that are made available in the std:: namespace like FILE or malloc() are they any problems with accessing them through the global namespace or is it just more idiomatic to access them as std::FILE or std::malloc()?
You should always include what the documentation tells you to. (C++ standard library implementations will often be written such that functions are reachable via other includes but of course relying on that means your code is not portable.) Note that there is no standard getline function in C. But there is one in C++:
std::getline()
is defined in header <string>. The C++ standard doesn't guarantee that, in general, C functions are available at global scope or are even part of the C++ standard library. The two languages began their divergence many years ago and so the idea that C++ is in a sense a superset of C - libraries included - is a myth.
Reference: https://en.cppreference.com/w/cpp/string/basic_string/getline
In relation to #3:
The .h libraries must place all its names in the global namespace and may also place them in the std:: namespace.
The c begining version must place all its names in the std:: namespace and may also place them in the global namespace.
It should be easy to link any C library with C++ in general, not just the standard headers.
Note that you may have to trawl through man to work out what version of what unix the method was introduced or if it is a specific extension, and decide for yourself if that historical startpoint is acceptable to you. But this is true if you wrote a C program instead of C++.
The C++ alias headers include most, but not all of the functionality from the C headers, but occasionally you may find the only way to get a function is to include the C header directly. On the other hand you need to ask yourself why they chose not to include that method, usually because it is deprecated, dangerous, or non-standard.
So the way it works, is that C functions, including C library functions are introduced with the extern "C" keyword.
When you #include C header files they will generally contain some code such as:
/* C++ needs to know that types and declarations are C, not C++. */
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
__BEGIN_DECLS
... which introduces a section of C interface functions.
If you needed to include a really old C library that did not do this, then you could easily add extern "C" around the #include:
extern "C" {
#include "ancientinterface.h"
};
You can also write your own methods that are "C" interface compatible.
I'm trying to include mongoose web server, which is written in C, and write the rest of the code in C++.
When compiling I get the error: redeclaration of C++ built-in type 'bool' in the mongoose header file in Code Blocks
#include <iostream>
#include "mongoose.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
return 0;
}
I enclosed the mongoose header in
#ifdef __cplusplus
extern "C"{
#endif
// header content
#ifdef __cplusplus
}
#endif
and I'm still getting the same error, at #include winsock2.h
C and C++ are different languages that share a common subset. You can compile most C declarations with a C++ compiler by putting them in a section specifying C linkage, as you show, but that follows from the sublanguage of C declarations being almost entirely within the shared subset of C and C++.
C++ has both more declarational features and more constraints than C does, however. In particular, the fact that it provides bool as a built-in type places a constraint that that identifier cannot be redeclared as a typedef name. C, on the other hand, has a standard header that defines exactly such a typedef, and it is not so uncommon for people to roll their own, too. Such typedefs will be rejected by a C++ compiler, C linkage notwithstanding.
If the C project is not already built with a mind toward providing for use by C++ programs, and simply wrapping the header inclusion in a C linkage block does not suffice, then you simply cannot use that library's header as-is. Your options are either to modify it or to provide an alternative. You might even need to provide a few wrapper functions, written in C, to serve as an interface with your C++ program. Details depend on the library you're trying to use.
If this is your only issue, then you could add #define bool C_INT_BOOL near your extern "C", then #undef bool near the }
In your cpp file I would write:
extern "C"{
#define bool C_INT_BOOL
#include "mongoose.h"
#undef bool
}
This allows the "C" interface to see the int parameter type, but shouldn't interfere with your c++ use of bool.
But I doubt this will be your only issue, in which case you will probaby quickly realise that adding an interface function layer is the safest way to go.
I know how to use extern "C" but what are the conditions when you have to use it?
extern "C" tells the C++ compiler not to perform any name-mangling on
the code within the braces. This allows you to call C functions from
within C++.
For example:
#include <string.h>
int main()
{
char s[] = "Hello";
char d[6];
strcpy_s(d, s);
}
While this compiles fine on VC++. But sometimes this is written as:
extern "C" {
#include <string.h>
}
I don't see the point. Can you give a real example where extern "C" is necessary?
You use extern "C" to prevent name mangling inside header files and your C++ object files for libraries or objects that have already been compiled without mangling.
For example, say you have a widget library which was compiled with a C compiler so that its published interface is non-mangled.
If you include the header file as is into your code, it will assume the names are mangled and those mangled versions are what you'll tell the linker to look for.
However, since you'll be asking for something like function#intarray_float_charptr and the widget library will have only published function, you're going to run into problems.
However, if you include it with:
extern "C" {
#include "widget.h"
}
your compiler will know that it should try to use function, the non-mangled version.
That's why, in header files for C stuff meant to be included in C _or C++ programs, you'll see things like:
#ifdef __cplusplus
extern "C" {
#endif
// Everything here works for both C and C++ compilers.
#ifdef __cplusplus
}
#endif
If you use a C compiler to include this, the #ifdef lines will cause the extern "C" stuff to disappear. For a C++ compiler (where __cplusplus is defined), everything will be non-mangled.
One very common use of extern "C" when you are exporting a function from a library. If you don't disable C++ name mangling you can otherwise make it very hard for clients of your library to name your function. And likewise, when going in the other direction, when you are importing a function that has been exported with C linkage.
Here is a concrete example of where things break and need extern "C" to get fixed.
module.h:
int f(int arg);
module.c:
int f(int arg) {
return arg + 1;
}
main.cpp:
#include "module.h"
int main() {
f(42);
}
Since I am mixing C and C++, this won't link (of the two object files, only one will know f under its C++ mangled name).
Perhaps the cleanest way to fix this is by making the header file compatible with both C and C++:
module.h:
#ifdef __cplusplus
extern "C" {
#endif
int f(int arg);
#ifdef __cplusplus
}
#endif
When you link with libraries that are written in C extern tells the compiler not to decorate the names so that the linker can find the functions. In C++ function names et al have information for the linker e.g. argument types and sizes contained in the name.
If you are producing a binary library A that exposes a function that you would like to call from binary B.
Imagine A is A.dll and B is B.exe and you are on a Windows system.
C++ does not describe a binary layout such that B knows how to call A. Typically this problem is worked around by using the same compiler to produce A and B. If you want a more generic solution you use the extern keyword. This exposes the function in a C manner. C does describe a binary format so that different binaries from different compilers can talk to each other.
See:
http://en.wikipedia.org/wiki/Application_binary_interface
http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B
If, inside your C++ code, you #include a header for an external library (coded in C) and if the functions there are not declared extern "C" they wont work (you'll get undefined reference at link time).
But these days, people coding C libraries and providing header files for you tend to know that, and often put the extern "C" in their header file (suitably protected with #ifdef __cplusplus)
Perhaps a better way to understand is to use (assuming you have a Linux system) the nm utility to show you the (unmangled) names used in a library or an executable.
I'm working on a project that has a lot of legacy C code. We've started writing in C++, with the intent to eventually convert the legacy code, as well. I'm a little confused about how the C and C++ interact. I understand that by wrapping the C code with extern "C" the C++ compiler will not mangle the C code's names, but I'm not entirely sure how to implement this.
So, at the top of each C header file (after the include guards), we have
#ifdef __cplusplus
extern "C" {
#endif
and at the bottom, we write
#ifdef __cplusplus
}
#endif
In between the two, we have all of our includes, typedefs, and function prototypes. I have a few questions, to see if I'm understanding this correctly:
If I have a C++ file A.hh which
includes a C header file B.h,
includes another C header file C.h,
how does this work? I think that
when the compiler steps into B.h,
__cplusplus will be defined, so it
will wrap the code with extern "C"
(and __cplusplus will not be
defined inside this block). So,
when it steps into C.h,
__cplusplus will not be defined
and the code will not be wrapped in
extern "C". Is this correct?
Is there anything wrong with
wrapping a piece of code with
extern "C" { extern "C" { .. } }?
What will the second extern "C"
do?
We don't put this wrapper around the .c files, just the .h files. So, what happens if a function doesn't have a prototype? Does the compiler think that it's a C++ function?
We are also using some third-party
code which is written in C, and does
not have this sort of wrapper around
it. Any time I include a header
from that library, I've been putting
an extern "C" around the #include.
Is this the right way to deal with
that?
Finally, is this set up a good idea?
Is there anything else we should do?
We're going to be mixing C and C++
for the foreseeable future, and I
want to make sure we're covering all
our bases.
extern "C" doesn't really change the way that the compiler reads the code. If your code is in a .c file, it will be compiled as C, if it is in a .cpp file, it will be compiled as C++ (unless you do something strange to your configuration).
What extern "C" does is affect linkage. C++ functions, when compiled, have their names mangled -- this is what makes overloading possible. The function name gets modified based on the types and number of parameters, so that two functions with the same name will have different symbol names.
Code inside an extern "C" is still C++ code. There are limitations on what you can do in an extern "C" block, but they're all about linkage. You can't define any new symbols that can't be built with C linkage. That means no classes or templates, for example.
extern "C" blocks nest nicely. There's also extern "C++" if you find yourself hopelessly trapped inside of extern "C" regions, but it isn't such a good idea from a cleanliness perspective.
Now, specifically regarding your numbered questions:
Regarding #1: __cplusplus will stay defined inside of extern "C" blocks. This doesn't matter, though, since the blocks should nest neatly.
Regarding #2: __cplusplus will be defined for any compilation unit that is being run through the C++ compiler. Generally, that means .cpp files and any files being included by that .cpp file. The same .h (or .hh or .hpp or what-have-you) could be interpreted as C or C++ at different times, if different compilation units include them. If you want the prototypes in the .h file to refer to C symbol names, then they must have extern "C" when being interpreted as C++, and they should not have extern "C" when being interpreted as C -- hence the #ifdef __cplusplus checking.
To answer your question #3: functions without prototypes will have C++ linkage if they are in .cpp files and not inside of an extern "C" block. This is fine, though, because if it has no prototype, it can only be called by other functions in the same file, and then you don't generally care what the linkage looks like, because you aren't planning on having that function be called by anything outside the same compilation unit anyway.
For #4, you've got it exactly. If you are including a header for code that has C linkage (such as code that was compiled by a C compiler), then you must extern "C" the header -- that way you will be able to link with the library. (Otherwise, your linker would be looking for functions with names like _Z1hic when you were looking for void h(int, char)
5: This sort of mixing is a common reason to use extern "C", and I don't see anything wrong with doing it this way -- just make sure you understand what you are doing.
extern "C" doesn't change the presence or absence of the __cplusplus macro. It just changes the linkage and name-mangling of the wrapped declarations.
You can nest extern "C" blocks quite happily.
If you compile your .c files as C++ then anything not in an extern "C" block, and without an extern "C" prototype will be treated as a C++ function. If you compile them as C then of course everything will be a C function.
Yes
You can safely mix C and C++ in this way.
A couple of gotchas that are colloraries to Andrew Shelansky's excellent answer and to disagree a little with doesn't really change the way that the compiler reads the code
Because your function prototypes are compiled as C, you can't have overloading of the same function names with different parameters - that's one of the key features of the name mangling of the compiler. It is described as a linkage issue but that is not quite true - you will get errors from both the compiler and the linker.
The compiler errors will be if you try to use C++ features of prototype declaration such as overloading.
The linker errors will occur later because your function will appear to not be found, if you do not have the extern "C" wrapper around declarations and the header is included in a mixture of C and C++ source.
One reason to discourage people from using the compile C as C++ setting is because this means their source code is no longer portable. That setting is a project setting and so if a .c file is dropped into another project, it will not be compiled as c++. I would rather people take the time to rename file suffixes to .cpp.
It's about the ABI, in order to let both C and C++ application use C interfaces without any issue.
Since C language is very easy, code generation was stable for many years for different compilers, such as GCC, Borland C\C++, MSVC etc.
While C++ becomes more and more popular, a lot things must be added into the new C++ domain (for example finally the Cfront was abandoned at AT&T because C could not cover all the features it needs). Such as template feature, and compilation-time code generation, from the past, the different compiler vendors actually did the actual implementation of C++ compiler and linker separately, the actual ABIs are not compatible at all to the C++ program at different platforms.
People might still like to implement the actual program in C++ but still keep the old C interface and ABI as usual, the header file has to declare extern "C" {}, it tells the compiler generate compatible/old/simple/easy C ABI for the interface functions if the compiler is C compiler not C++ compiler.
This question already has answers here:
What is the effect of extern "C" in C++?
(17 answers)
Closed 8 years ago.
Maybe I'm not understanding the differences between C and C++, but when and why do we need to use
extern "C" {
? Apparently its a "linkage convention".
I read about it briefly and noticed that all the .h header files included with MSVS surround their code with it. What type of code exactly is "C code" and NOT "C++ code"? I thought C++ included all C code?
I'm guessing that this is not the case and that C++ is different and that standard features/functions exist in one or the other but not both (ie: printf is C and cout is C++), but that C++ is backwards compatible though the extern "C" declaration. Is this correct?
My next question depends on the answer to the first, but I'll ask it here anyway: Since MSVS header files that are written in C are surrounded by extern "C" { ... }, when would you ever need to use this yourself in your own code? If your code is C code and you are trying to compile it in a C++ compiler, shouldn't it work without problem because all the standard h files you include will already have the extern "C" thing in them with the C++ compiler?
Do you have to use this when compiling in C++ but linking to already built C libraries or something?
You need to use extern "C" in C++ when declaring a function that was implemented/compiled in C. The use of extern "C" tells the compiler/linker to use the C naming and calling conventions, instead of the C++ name mangling and C++ calling conventions that would be used otherwise. For functions provided by other libraries, you will almost never need to use extern "C", as well-written libraries will already have this in there for the public APIs that it exports to both C and C++. If, however, you write a library that you want to make available both in C and in C++, then you will have to conditionally put that in your headers.
As for whether all C code is C++ code... no, that is not correct. It is a popular myth that C++ is a "superset of C". While C++ certainly strives to be as compatible with C as possible, there are some incompatibilities. For example, bool is valid C++ but not valid C, while _Bool exists in C99, but is not available in C++.
As to whether you will ever need to use extern "C" with the system's ".h" files.... any well-designed implementation will have those in there for you, so that you do not need to use them. However, to be certain that they are provided, you should include the equivalent header file that begins with "c" and omits ".h". For example, if you include <ctype.h>, almost any reasonable system will have the extern "C" added; however, to be assured a C++-compatible header, you should instead include the header <cctype>.
You may also be interested in Mixing C and C++ from the C++ FAQ Lite.
The other answers are correct, but a complete "boilerplate" example will probably help. The canonical method for including C code in C and/or C++ projects is as follows:
//
// C_library.h
//
#ifdef __cplusplus
extern "C" {
#endif
//
// ... prototypes for C_library go here ...
//
#ifdef __cplusplus
}
#endif
-
//
// C_library.c
//
#include "C_library.h"
//
// ... implementations for C_library go here ...
//
-
//
// C++_code.cpp
//
#include "C_library.h"
#include "C++_code.h"
//
// ... C++_code implementation here may call C functions in C_library.c ...
//
Note: the above also applies to calling C code from Objective-C++.
C++ compilers mangle the names in their symbol table differently than C compilers. You need to use the extern "C" declaration to tell the C++ compiler to use the C mangling convention instead when building the symbol table.
I use 'extern c' so that C# can read my C++ code without having to figure out the extra name mangling done when exporting a C++ dll function. Otherwise, there are extra nonsensical (or really, non-English) characters that I have to add at the end of a function entry point on the C# side in order to properly access a C++ function in a dll.
extern "C" {} blocks tell a C++ compiler to use the C naming and calling conventions. If you don't use this you will get linker errors if trying to include a C library with your C++ project because C++ will mangle the names. I tend to use this on all my C headers just in case they are ever used in a C++ project:
#ifdef __cplusplus
extern "C" {
#endif
/* My library header */
#ifdef __cplusplus
} // extern
#endif
You need to use extern "C" when you want to use the C calling convention in code compiled by a C++ compiler. There are two reasons for this:
You have a function implemented in C and want to call it from C++.
You have a function implemented in C++ and want to call it from C. Note that in this case you can only use the C part of C++ in the function interface (no classes, ...).
Apart from C this also applies when you want to interoperate between C++ and other languages which use the same calling and naming conventions as C.
Typically the declarations in a C header file are surrounded with
#ifdef __cplusplus
extern "C" {
#endif
[... C declarations ...]
#ifdef __cplusplus
}
#endif
to make it usable from C++.
C++ functions are subject to name mangling. This makes them impossible to call directly from C code unless extern "C" is used.