web analytics
How to call C functions from C++ and vice versa? Options
davegate
Posted: Monday, February 1, 2016 6:29:04 PM

Rank:Advanced Member
Groups: Member
Joined: 12/14/2015
Posts: 182
Points: 894

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.

Sponsor
Posted: Monday, February 1, 2016 6:29:04 PM
davegate
Posted: Monday, February 1, 2016 6:32:57 PM

Rank:Advanced Member
Groups: Member
Joined: 12/14/2015
Posts: 182
Points: 894

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.

davegate
Posted: Monday, February 1, 2016 7:37:02 PM

Rank:Advanced Member
Groups: Member
Joined: 12/14/2015
Posts: 182
Points: 894

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
   ...
 }

 

davegate
Posted: Monday, February 1, 2016 11:34:10 PM

Rank:Advanced Member
Groups: Member
Joined: 12/14/2015
Posts: 182
Points: 894

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.
Users browsing this topic
Guest

Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.


© 2018 Digcode.com. All rights reserved.