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:CFile.c: In function 'main': CFile.c:3:11: warning: implicit declaration of function 'sqrt' [-Wimplicit-function-declaration] int i = sqrt(25.0); ^ CFile.c:3:11: warning: incompatible implicit declaration of built-in function 'sqrt' CFile.c:3:11: note: include '' or provide a declaration of 'sqrt' CFile.c:5:3: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration] printf("In C: i = %i, d = %g\n", i, d); ^ CFile.c:5:3: warning: incompatible implicit declaration of built-in function 'printf' CFile.c:5:3: note: include ' ' or provide a declaration of 'printf'
#include <math.h> #include <stdio.h>
This suppresses the warnings about the functions being unknown. However, we still may get a warning for trying to assign a double to an integer. 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:
Now the file will compile without warnings or errors. Note that not all compilers will warn about the possible loss of data.int i = (int)sqrt(25.0);
CPPFile.cpp: In function 'void cpp_stuff()': CPPFile.cpp:3:20: error: 'sqrt' was not declared in this scope int i = sqrt(25.0); ^ CPPFile.cpp:5:42: error: 'printf' was not declared in this scope printf("In CPP: i = %i, d = %g\n", i, d); ^
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++:
Or, if you would rather use the "C" versions of the header files (without the extension), you can do this:#include <math.h> #include <stdio.h> int i = static_cast<int>(sqrt(25));
and then use std:: with each function. The C++ code now compiles without warnings or errors.#include <cmath> #include <cstdio>
Wrapping C header files in C++
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:In C: i = 5, d = 5
This code generates a warning during the compile and an error during the link.void main(void) { int i = (int) sqrt(25); double d = sqrt(25); printf("In C: i = %i, d = %g\n", i, d); cpp_stuff(); }
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.CFile.c: In function 'main': CFile.c:9:3: warning: implicit declaration of function 'cpp_stuff' [-Wimplicit-function-declaration] cpp_stuff(); ^ /tmp/cc6hK5Dl.o: In function `main': CFile.c:(.text+0x43): undefined reference to `cpp_stuff' collect2: error: ld returned 1 exit status
To fix the compiler warning, we prototype the function before main:
To fix the linker error, we need to tell the C++ compiler to disable name mangling during the compile by using the extern keyword and then recompile the C++ file:void cpp_stuff(void);
Now we can build the C file and link with the C++ object file: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 output from the program looks like:gcc CFile-original.c CPPFile-original.o -o mix
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);
}