Tuesday, August 04, 2009

Mixing C and C++ Code in the Same Program


By Stephen Clamage, Sun Microsystems, Sun ONE Studio Solaris Tools Development Engineering  
The C++ language provides mechanisms for mixing code that is compiled by compatible C and C++ compilers in the same program. You can experience varying degrees of success as you port such code to different platforms and compilers. This article shows how to solve common problems that arise when you mix C and C++ code, and highlights the areas where you might run into portability issues. In all cases we show what is needed when using Sun C and C++ compilers.
Using Compatible Compilers
Accessing C Code From Within C++ Source
Accessing C++ Code From Within C Source
Mixing IOstream and C Standard I/O
Working with Pointers to Functions
Working with C++ Exceptions
Linking the Program
Using Compatible Compilers

The first requirement for mixing code is that the C and C++ compilers you are using must be compatible. They must, for example, define basic types such as int, float or pointer in the same way. The Solaris Operating System (Solaris OS) specifies the Application Binary Interface (ABI) of C programs, which includes information about basic types and how functions are called. Any useful compiler for the Solaris OS must follow this ABI.

Sun C and C++ compilers follow the Solaris OS ABI and are compatible. Third-party C compilers for the Solaris OS usually also follow the ABI. Any C compiler that is compatible with the Sun C compiler is also compatible with the Sun C++ compiler.

The C runtime library used by your C compiler must also be compatible with the C++ compiler. C++ includes the standard C runtime library as a subset, with a few differences. If the C++ compiler provides its own versions of of the C headers, the versions of those headers used by the C compiler must be compatible.

Sun C and C++ compilers use compatible headers, and use the same C runtime library. They are fully compatible.

Accessing C Code From Within C++ Source

The C++ language provides a "linkage specification" with which you declare that a function or object follows the program linkage conventions for a supported language. The default linkage for objects and functions is C++. All C++ compilers also support C linkage, for some compatible C compiler.

When you need to access a function compiled with C linkage (for example, a function compiled by the C compiler), declare the function to have C linkage. Even though most C++ compilers do not have different linkage for C and C++ data objects, you should declare C data objects to have C linkage in C++ code. With the exception of the pointer-to-function type, types do not have C or C++ linkage.


Declaring Linkage Specifications
Use one of the following notations to declare that an object or function has the linkage of language language_name:

extern "language_name" declaration ; extern "language_name" { declaration ; declaration ; ... }       

The first notation indicates that the declaration (or definition) that immediately follows has the linkage of language_name. The second notation indicates that everything between the curly braces has the linkage of language_name, unless declared otherwise. Notice that you do not use a semicolon after the closing curly brace in the second notation.

You can nest linkage specifications, but they do not create a scope. Consider the following example:

extern "C" {     void f();             // C linkage     extern "C++" {         void g();         // C++ linkage         extern "C" void h(); // C linkage         void g2();        // C++ linkage     }     extern "C++" void k();// C++ linkage     void m();             // C linkage }       

All the functions above are in the same global scope, despite the nested linkage specifiers.


Including C Headers in C++ Code
If you want to use a C library with its own defining header that was intended for C compilers, you can include the header in extern "C" brackets:

extern "C" {     #include "header.h" }       
Do not use this technique for system headers on the Solaris OS. The Solaris headers, and all the headers that come with Sun C and C++ compilers, are already configured for use with C and C++ compilers. You can invalidate declarations in the Solaris headers if you specify a linkage.

Creating Mixed-Language Headers
If you want to make a header suitable for both C and C++ compilers, you could put all the declarations inside extern "C" brackets, but the C compiler does not recognize the syntax. Every C++ compiler predefines the macro __cplusplus, so you can use that macro to guard the C++ syntax extensions:

#ifdef __cplusplus extern "C" { 

No comments: