Compiling CFile.c

The C file gives two compiler warnings something like:
cfile.c(3) : warning C4013: 'sqrt' undefined; assuming extern returning int
cfile.c(5) : warning C4013: 'printf' undefined; assuming extern returning int
These warnings indicate that the compiler doesn't know what kinds of functions sqrt and printf are, so it assumes that they return an int, which is usually a poor assumption. To clue the compiler in as to their types, we need to specify the proper prototypes. This is easily done by including the header files where these functions are prototyped:
#include <math.h>
#include <stdio.h>
This suppresses the warnings about the functions being unknown. However, we are now getting another warning:
CFile.c(8) : warning C4244: 'initializing' : conversion from 'double ' to 'int ', possible loss of data
This is because the sqrt function returns a double, yet we are assigning it to an int. To suppress this warning, we need to cast the return value to an int
int i = (int)sqrt(25);
Now the file will compile without warnings or errors.


Compiling CPPFile.cpp:

The C++ file has the same problems as the C file. However, if a function is called that the compiler hasn't seen yet, the compiler generates an error instead of a warning. We need to add the two includes as well as a cast. We can use a C++ cast in this case because we the code is C++:
#include <math.h>
#include <stdio.h>

int i = static_cast<int>(sqrt(25));
Or, if you would rather use the "c" versions of the header files (without the extension), you can do this:
#include <cmath>
#include <cstdio>
The C++ code now compiles without warnings or errors.

Wrapping C header files in C++


Linking the files and calling the C++ function from C

The program links without warnings or errors and generates this output:
In C: i = 5, d = 5
So we are almost there. To get the output from the C++ code, we need to call the C++ function from the C code by adding a call to it in main:
void main(void)
{
  int i = (int) sqrt(25);
  double d = sqrt(25);
  printf("In C: i = %i, d = %g\n", i, d);
  cpp_stuff();
}
This code generates a warning during the compile and an error during the link.
CFile.c(9) : warning C4013: 'cpp_stuff' undefined; assuming extern returning int
Linking...
CFile.obj : error LNK2001: unresolved external symbol _cpp_stuff
Debug/CandCPP.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
The reason the compiler generates a warning is because it doesn't know what cpp_stuff is. (The same problem we had with sqrt and printf). So, we need to prototype it in our C file. (We don't have a header file that we can include.) The linker error is because the C++ compiler mangled the function name into a non-C compatible function name.

To fix the compiler warning, we prototype the function before main:

void cpp_stuff(void);
To fix the linker error, we need to tell the C++ compiler to disable name mangling during the compile by using the extern keyword:
extern "C" void cpp_stuff(void)
{
  ...
}
This fixes all of the problems we encountered when we attempted mix C and C++ code in the same project. The entire project will compile and link without warnings or errors. The output from the program looks like:
In C: i = 5, d = 5
In CPP: i = 5, d = 5


The complete code for both files:

CFile.c:


#include <math.h>   // for sqrt()
#include <stdio.h>  // for printf()

void cpp_stuff(void);

void main(void)
{
  int i = (int) sqrt(25);
  double d = sqrt(25);
  printf("In C: i = %i, d = %g\n", i, d);
  cpp_stuff();
}
CPPFile.cpp:

#include <math.h>   // for sqrt()
#include <stdio.h>  // for printf()

// use extern "C" so the C file can link to this
extern "C" void cpp_stuff(void)
{
  int i = (int)sqrt(25);
  double d = sqrt(25);
  printf("In CPP: i = %i, d = %g\n", i, d);
}