There are several caveats:
In addition, you'll need to read the rest of this section to find out how to make your C functions callable by C++ and/or your C++ functions callable by C.
[ Top | Bottom | Previous section | Next section ]
To #include a standard header file (such as <cstdio>), you don't have to do anything unusual. E.g.,
Note: Somewhat different guidelines apply for non-system C headers. There are two cases: either you can't change the header, or you can change the header.
[ Top | Bottom | Previous section | Next section ]
If you are including a C header file that isn't provided by the system, you may need to wrap the #include line in an extern C { /*...*/ } construct. This tells the C++ compiler that the functions declared in the header file are are C functions.
Note: Somewhat different guidelines apply for C headers provided by the system (such as <cstdio>) and for C headers that you can change.
[ Top | Bottom | Previous section | Next section ]
If you are including a C header file that isn't provided by the system, and if you are able to change the C header, you should strongly consider adding the extern C {...} logic inside the header to make it easier for C++ users to #include it into their C++ code. Since a C compiler won't understand the extern C construct, you must wrap the extern C { and } lines in an #ifdef so they won't be seen by normal C compilers.
Step #1: Put the following lines at the very top of your C header file (note: the symbol __cplusplus is #defined if/only-if the compiler is a C++ compiler):
Step #2: Put the following lines at the very bottom of your C header file:
Now you can #include your C header without any extern C nonsense in your C++ code:
Note: Somewhat different guidelines apply for C headers provided by the system (such as <cstdio>) and for C headers that you can't change.
Note: #define macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4. But they're still useful sometimes. Just wash your hands after using them.
[ Top | Bottom | Previous section | Next section ]
If you have an individual C function that you want to call, and for some reason you don't have or don't want to #include a C header file in which that function is declared, you can declare the individual C function in your C code using the extern C syntax. Naturally you need to use the full function prototype:
A block of several C functions can be grouped via braces:
After this you simply call the function just as if it was a C++ function:
[ Top | Bottom | Previous section | Next section ]
The C++ compiler must know that f(int,char,float) is to be called by a C compiler using the extern C construct:
The extern C line tells the compiler that the external information sent to the linker should use C calling conventions and name mangling (e.g., preceded by a single underscore). Since name overloading isn't supported by C, you can't make several overloaded functions simultaneously callable by a C program.
[ Top | Bottom | Previous section | Next section ]
If you didn't get your extern C right, you'll sometimes get linker errors rather than compiler errors. This is due to the fact that C++ compilers usually "mangle" function names (e.g., to support function overloading) differently than C compilers.
See the previous two FAQs on how to use extern C.
[ Top | Bottom | Previous section | Next section ]
Here's an example (for info on extern C, see the previous two FAQs).
Fred.h:
Fred.cpp:
main.cpp:
c-function.c:
Passing pointers to C++ objects to/from C functions will fail if you pass and get back something that isn't exactly the same pointer. For example, don't pass a base class pointer and receive back a derived class pointer, since your C compiler won't understand the pointer conversions necessary to handle multiple and/or virtual inheritance.
[ Top | Bottom | Previous section | Next section ]
Sometimes.
(For basic info on passing C++ objects to/from C functions, read the previous FAQ).
You can safely access a C++ object's data from a C function if the C++ class:
If the C++ class has any base classes at all (or if any fully contained subobjects have base classes), accessing the data will technically be non-portable, since class layout under inheritance isn't imposed by the language. However in practice, all C++ compilers do it the same way: the base class object appears first (in left-to-right order in the event of multiple inheritance), and member objects follow.
Furthermore, if the class (or any base class) contains any virtual functions, almost all C++ compliers put a void* into the object either at the location of the first virtual function or at the very beginning of the object. Again, this is not required by the language, but it is the way "everyone" does it.
If the class has any virtual base classes, it is even more complicated and less portable. One common implementation technique is for objects to contain an object of the virtual base class (V) last (regardless of where V shows up as a virtual base class in the inheritance hierarchy). The rest of the object's parts appear in the normal order. Every derived class that has V as a virtual base class actually has a pointer to the V part of the final object.
[ Top | Bottom | Previous section | Next section ]
Because you are.
As an OO programming language, C++ allows you to model the problem domain itself, which allows you to program in the language of the problem domain rather than in the language of the solution domain.
One of C's great strengths is the fact that it has "no hidden mechanism": what you see is what you get. You can read a C program and "see" every clock cycle. This is not the case in C++; old line C programmers (such as many of us once were) are often ambivalent (can you say, "hostile"?) about this feature. However after they've made the transition to OO thinking, they often realize that although C++ hides some mechanism from the programmer, it also provides a level of abstraction and economy of expression which lowers maintenance costs without destroying run-time performance.
Naturally you can write bad code in any language; C++ doesn't guarantee any particular level of quality, reusability, abstraction, or any other measure of "goodness."
C++ doesn't try to make it impossible for bad programmers to write bad programs; it enables reasonable developers to create superior software.
[ Top | Bottom | Previous section | Next section ]
E-mail the author
[ C++ FAQ Lite
| Table of contents
| Subject index
| About the author
| ©
| Download your own copy ]
Revised Jul 10, 2000