C++ Migration Guide

Language Linkage

Language linkage means the way in which a function is called: where the arguments are placed, where the return value is to be found, and so on. Declaring a language linkage does not mean the function is written in that language. It means that the function is called as if it were written in that language. Thus, declaring a C++ function to have C linkage means the C++ function can be called from a function written in C.

A language linkage applied to a function declaration applies to the return type and all its parameters that have function or pointer-to-function type.

The C++ 4.2 compiler implements the ARM rule that the language linkage is not part of the function type. In particular, you can declare a pointer to a function without regard to the linkage of the pointer, or of a function assigned to it. The C++ 5.0 compiler in compatibility mode uses the same rule.

The C++ 5.0 compiler in standard mode implements the new rule that the language linkage is part of its type, and is part of the type of a pointer to function. The linkages must therefore match.

The following example shows functions and function pointers with C and C++ linkage, in all four possible combinations. The 4.2 compiler and the 5.0 compiler in compatibility mode accept all combinations. The 5.0 compiler in standard mode accepts the mismatched combinations only as an anachronism.


extern "C" int fc(int) { return 1; }      // fc has C linkage
int fcpp(int) { return 1; }               // fcpp has C++ linkage
// fp1 and fp2 have C++ linkage
int (*fp1)(int) = fc;                     // Mismatch
int (*fp2)(int) = fcpp;                   // OK 
// fp3 and fp4 have C linkage 
extern "C" int (*fp3)(int) = fc;          // OK 
extern "C" int (*fp4)(int) = fcpp;        // Mismatch

If you encounter a problem, be sure that the pointers to be used with C linkage functions are declared with C linkage, and the pointers to be used with C++ linkage functions are declared without a linkage specifier, or with C++ linkage. For example:


extern "C" {
    int fc(int);
    int (*fp1)(int) = fc; // Both have C linkage
}
int fcpp(int); 
int (*fp2)(int) = fcpp;   // Both have C++ linkage

In the worst case, where you really do have mismatched pointer and function, you can write a "wrapper" around the function to avoid any compiler complaints. (On Solaris, C and C++ function linkage is the same. However, in the most general case, the mismatched linkage really is an error. Hence the new language rule.)

In the following example, composer is a C function taking a pointer to a function with C linkage.


extern "C" void composer( int(*)(int) );
extern "C++" int foo(int); 
composer( foo ); // Mismatch

To pass function foo (which has C++ linkage) to the function composer, create a C-linkage function foo_wrapper that presents a C interface to foo:


extern "C" void composer( int(*)(int) );
extern "C++" int foo(int);
extern "C" int foo_wrapper(int i) { return foo(i); }
composer( foo_wrapper ); // OK

In addition to eliminating the compiler complaint, this solution works even if C and C++ functions really have different linkage.