How To Use C with C++

August 5, 2019

If you’ve tried to use C++ and C files in the same project, you’ve probably also run into problems linking the two. A problem specific to this setup is resolving linkages between two files with .c and .cpp extensions.  

If you haven’t heard of name mangling, it’s a feature of C++ that allows the compiler to add information to compilation items due to the support for things like namespaces and operator overloading. It’s useful to make the linker’s job easier, but can be problematic since it changes the names of your functions! Lets look at an example.

printString() function is defined in the printString.c file and prototyped in the printString.h file

In this sample project I have both a .c and .cpp file. The .cpp file contains the main function and is calling a function defined in a .c file.

If the header is included normally, we get an error. In this error, the linker is telling us that it can’t find the definition for the printString function. Why is this happening? Well lets look at what the builder is giving the linker to find the problem.

I used a program included with Visual Studio called DumpBin to see the assembly code the builder is producing. If we look at the main function disassembly, we can see something strange. Our printString function has a bunch of seemingly random characters in the function call! This is “name mangling” in action. It has different appearances depending on what c++ compiler you’re using, but this is essentially what it does. Thankfully there’s an easy fix for this.

Our original error
Name mangling in action!

If we use any header files that link to a .c file in a .cpp file, we must enclose them in the extern “C” keyword. This ensures that our C++ compiler will not mangle the names and cause the linker to be unable to resolve them.

#include <iostream>

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

using namespace std; 

int main(void) 
{

	printString("Hello");

	while (1) {}

	return 0; 
}
Our Assembly with the extern “C” keyword around the .h file

Another method is to enclose the header file itself in an extern “C”. If you do this you just have to be careful to enclose the keyword itself in a preprocessor gaurd that first checks if the compiler is c++ using #ifdef __cplusplus.

// printString.h
#ifdef __cplusplus 
extern "C" {
#endif 

void printString(const char * string);

#ifdef __cplusplus
}
#endif 

Both techniques work equally well and it’s up to you which to use.  

Leave a Reply