
If you have a project which is written in C/C++ where you are seeing the parts of code has been implemented in C
and some part in C++.Then you might have observed that user might have the need to call C function from C++ code and vice-versa.
Let’s see how we can do this.
Requirement: Compilers should be Compatible
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 probably easiest way to use C functionality in a C++ program is to simply compile the C code as C++ code.
This will, however, not work reliably.
So, we have to compile the C code as C, and the C++ code as C++.
For simplicity, let’s assume we have a function void fun(int) that has been defined in one source file and
gets called in another source file.
In C, the compiler generates a simple symbol fun for that function – this is defined in the C standard.
In C++, we can have much more than one function named fun: we have different namespaces, classes with
member functions, and overloaded functions that take different parameters. Therefore, the C++ compiler
can not simply create a symbol fun. It has to generate names that contain all that information. The
process is called name mangling and is not standardized.
Let’s assume, fun is a C function which we want to call from main in our C++ program:
//main.cpp
#include "fun.h"
int main()
{
fun(14);
}
//fun.h
void fun(int);
#include <stdio.h>
//fun.c
void fun(int x) {
printf("%d", x);
}
When we compile the whole thing, the linker will give us an error: The C++ compiler will see the declaration of void fun(int) and the call to that function and generate a mangled name, say, void@fun(int). The C compiler will simply generate the symbol foo. The linker will, therefore, complain that it can not find void@fun(int), because that symbol simply does not exist.
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.
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 the braces do not create scopes. Consider the following example:
extern "C" {
void f1(); // C linkage
extern "C++" {
void g1(); // C++ linkage
extern "C" void h1(); // C linkage
void g2(); // C++ linkage
}
extern "C++" void k1(); // C++ linkage
void m1(); // C linkage
}
Just declare the C function extern "C" (in your C++ code) and call it (from your C or C++ code). For example:
// C++ code
extern "C" void f1(int); // one way
extern "C" { // another way
int g1(double);
double h1();
};
void example(int i, double d)
{
f(i);
int ii = g1(d);
double dd = h1();
// ...
}
The definitions of the functions may look like this:
/* C code: */
void f1(int i)
{
/* ... */
}
int g1(double d)
{
/* ... */
}
double h1()
{
/* ... */
}
Note that C++ type rules, not C rules, are used. So you can’t call function declared extern "C" with the wrong number of arguments. For example:
// C++ code
void more_code(int i, double d)
{
double dd = h1(i,d); // error: unexpected arguments
// ...
}
How do I call a C++ function from C?
Just declare the C++ function extern "C" (in your C++ code) and call it (from your C or C++ code). For example:
// C++ code:
extern "C" void f1(int);
void f1(int i)
{
// ...
}
Now f1() can be used like this:
/* C code: */
void f1(int);
void cc(int i)
{
f1(i);
/* ... */
}
Naturally, this works only for non-member functions. If you want to call member functions (incl. virtual functions) from C, you need to provide a simple wrapper. For example:
// C++ code:
class C {
// ...
virtual double f1(int);
};
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f1(i);
}
Now C::f1() can be used like this:
/* C code: */
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
double d = call_C_f(p,i);
/* ... */
}