I am following an intro tutorial http://www.linuxinsight.com/files/alp/alp-ch01-getting-started.pdf.
I have created the source files main.c, reciprocal.cpp and reciprocal.hpp. I have been able to successfully compile these files. The problem comes when I go to link them and I receive the following error message:
main.o: In function `main':
main.c:(.text+0x30): undefined reference to `reciprocal'
collect2: ld returned 1 exit status
I gather that this is somehow not using the header files correctly, however I do not really know what to try as I've followed the steps quite thoroughly.
If anyone has an idea why its throwing that error I would appreciate it very much.
Thanks
**UPDATE Here is the code for the three source files:
main.c
#include <stdio.h>
#include "reciprocal.hpp"
int main (int argc, char **argv) {
int i;
i = atoi(argv[1]);
printf("The reciprocal of %d is %g\n", i, reciprocal(i));
return 0;
}
reciprocal.cpp
#include <cassert>
#include "reciprocal.hpp"
double reciprocal(int i) {
assert(i != 0);
return 1.0/i;
}
reciprocal.hpp
#ifdef __cplusplus
extern "C" {
#endif
double reciprocal(int i);
#ifdef __cplusplus
}
#endif
I have actually modified reciprocal.hpp since originally posting. The only change I've made was to remove the extern keyword from the function signature. It previously read
extern double reciprocal(int i);
This change allowed me to link the program and I can now run it. I think what may have been occurring is that the second extern was overriding the first one. If anyone has any insight on this, I would be interested in knowing.
Thanks for your assistance everyone.
When you mix C and C++ code together, you can run into trouble because the two languages have different linkages. That is, if you were to crack open the object files for a compiled C and C++ file, you would find that the names inside of those object files were different.
In particular, C++ compilers tend to use a technique called "name mangling" in which function names are mixed with extra information about the types of their arguments. For example, a function
char foo(int);
might actually have the internal name
char@foo@int
inside of the generated object file. The problem is that C code does not do this, so if you compiled a C file and tried to make a reference to the name foo, the linker wouldn't find it, because the name of the function in the generated C++ file is char@foo@int instead of foo.
To fix this, C++ has a feature that allows you to explicitly tell the linker not to mangle the name and to make the generated code look like it was intended for a C program. To do this, you can declare C++ functions like this:
extern "C" char foo(int);
Now, the generated object file will contain the name foo without adornment in a way that is compatible with what the C code expects.
To fix your problem, try adding one of these extern "C" declarations to your C++ source file that defines reciprocal.
A note: if you have a project that mixes C and C++ code, you should always have the main function compiled as C++ code. C++ introduces extra initialization and cleanup code into its executables that are not present in C code. If you compile main as C code, this extra logic might not get added into the program, and so you may get inexplicable crashes at runtime.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With