web analytics

How to call C functions from C++ and vice versa?

Options

davegate 143 - 921
@2016-02-01 18:29:04

Because of the well-known name managling mechanism used in C++ compilers, a C++ function compiled by a C++ compiler cannot be called by C programs directly. Similarly, if a library file is compiled by a C compiler, then none of the functions in the library is accessible from C++ codes by default. The postings in this topic explain what name mangling is and how to stop it to make C functions are callable from C++ and vice versa.

C++ Name Mangling

Name mangling is the encoding of function and variable names into unique names so that linkers can separate common names in the language. Type names may also be mangled. The compiler generates function names with an encoding of the types of the function arguments when the module is compiled. Name mangling is commonly used to facilitate the overloading feature and visibility within different scopes. Name mangling also applies to variable names. If a variable is in a namespace, the name of the namespace is mangled into the variable name so that the same variable name can exist in more than one namespace. The C++ compiler also mangles C variable names to identify the namespace in which the C variable resides.

For example for the below C code:

int foo(double*);
double bar(int, double*);

int foo (double* d) 
{
    return 1;
}

double bar (int i, double* d) 
{
    return 0.9;
}

Its symbol table would be

[4]  0x18   44    2 1 0 0x2 bar
[5]  0x0    24    2 1 0 0x2 foo

For same file, if compile in a C++ compiler like g++, then the symbol table would be

[4]  0x0    24    2  1 0 0x2 _Z3fooPd
[5]  0x18   44    2  1 0 0x2 _Z3bariPd

``_Z3bariPd'' means a function whose name is bar and whose first arg is integer and second argument is pointer to double.

@2016-02-01 18:32:57

Having been said above, names may not be mangled as C doesn’t support function overloading. So how to make sure that name of a symbol is not changed when we link a C code in C++. For example, see the following C++ program that uses printf() function of C.

// Save file as .cpp and use C++ compiler to compile it

int printf(const char *format,...);


int main()

{

    printf("GeeksforGeeks");

    return 0;

}

Output:

undefined reference to `printf(char const*, ...)' ld returned 1 exit status

The reason for compiler error is simple, name of printf is changed by C++ compiler and it doesn’t find definition of the function with new name.

@2016-02-01 19:37:02

Calling C Functions from C++

To prevent the C++ compiler from mangling the name of a C function, you can apply the extern "C" linkage specifier to the declaration or declarations, as shown in the following example:

//C++ code

//One C function
extern "C" void f(int);

//More than one C funtions
extern "C" {
   int f1(int);
   int f2(double);
   int f3(int);
};

int main()
{
   f(3);
 
   int i = f1(4);
   // ...
}

If you know a library file is compiled by a C compiler, and you want to call the functions contained in this library from C++ codes, you have to include the corresponding head file using this mechanism.

//C++ code

extern "C"
{
#include "cinclude.h"
}

int main()
{
   f(3);// void f(int) is declared in cinclude.h
   ...
}

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.

/* cinclude.h */

#ifdef __cplusplus
extern "C" {
#endif

/* C-functions */
int f(int);

#ifdef __cplusplus
}
#endif

Why is extern “C“ surrounded with #ifdef and #endif? this is because a C compiler won't understand the extern "C" construct, you have to wrap the extern "C" { and } lines in an #ifdef so they won't be seen by normal C compilers. The standard C library header files, such as stdio.h, are built in this manner.

Now you can #include your C header without any extern "C" linkage specifier in your C++ code:

 // C++ code
 
 #include "cinclude.h" 
 
 int main()
 {
   f(3);       // Note: nothing unusual in the call
   ...
 }

 

@2016-02-01 23:34:10

Following are main points discussed above

  • Since C++ supports function overloading, additional information has to be added to function names (called name mangling) to avoid conflicts in binary code.
  • Function names may not be changed in C as C doesn’t support function overloading. To avoid linking problems, C++ supports extern “C” block. C++ compiler makes sure that names inside extern “C” block are not changed.

Comments

You must Sign In to comment on this topic.


© 2024 Digcode.com