Jeff
Jeff

Reputation: 70

Undefined reference from C++ to variables/functions defined in C file

I've been given a package of files (one .cpp, and some .c and .h) and want to make some modifications. But right now I'm just trying to get the original version to compile (in Linux).

Here's a (really) minimal working example:

mainfile.cpp

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

int main(int argc, char * argv[]){
getfoo(temperature);
return 0;}

auxfile.h

#define PUBLIC
#define PRIVATE static
extern int temperature;
int   getfoo(  int inputint);

auxfile.c

#include "auxfile.h"
int temperature = 37;
PUBLIC int getfoo(  int inputint){
return 7;
}

When I type

g++ mainfile.cpp

I get

mainfile.cpp(.text+0x11): undefined reference to `temperature'
mainfile.cpp(.text+0x18): undefined reference to `getfoo'
collect2: ld returned 1 exit status

For what it's worth, I've looked through numerous "undefined reference" questions and spent dozens of hours working on my own. The above code presents the essence of the problem. Any help would be massively appreciated. Thanks.

Upvotes: 2

Views: 87

Answers (1)

user2371524
user2371524

Reputation:

At the time of linking, all symbols (except those for dynamic linking, aka shared libraries) have to be defined. To create an object file with possibly unresolved symbols for later linking, there is the -c flag, that means just compile, do not link.

So, the following would work:

g++ -c -omainfile.o mainfile.cpp
gcc -c -oauxfile.o auxfile.c
g++ -o mainfile mainfile.o auxfile.o

Only the last line actually invokes the linker and as you have both object files, all symbols are found.

Just for completeness, in a real-world scenario you'd handle compiling and linking using make. Create a Makefile with the following contents:

OBJS:= mainfile.o auxfile.o

all: mainfile

# $@ means what to build (in this case "mainfile"), $^ is replaced by all
# dependencies (here the contents of the variable OBJS)
mainfile: $(OBJS)
        g++ -o$@ $^

# pattern for *.cpp -> create a *.o file with same name using g++
%.o: %.cpp
        g++ -c -o$@ $<

# the same for *.c, but using gcc here
%.o: %.c
        gcc -c -o$@ $<

clean:
        rm -f $(OBJS)

# "PHONY" are targets, that are not actually the names of output files
.PHONY: all clean

Then just type make and see the "magic" happening. Of course this is just for starters, no dependencies are tracked etc...

Upvotes: 4

Related Questions