Calling a function from another C file - c

I am writing a graphics program in C/C++ using OpenGL. I have a bunch of .c files and right now, I am trying to call a function from main.cpp in assignment1gui.c. The teacher has given me a file with the compile code. It looks like this:
OBJS = assignment1gui.o shadertools.o main.o
TARGET = ass1
CXX = gcc
DBFLAGS = -O0 -g3 -ggdb3 -fno-inline
WFLAGS = -Wall -ansi
GLFLAGS = `pkg-config --cflags gtk+-2.0`
LGLFLAGS = `pkg-config --libs gtk+-2.0` -lGL -lGLEW -lGLU -lglut
CXXFLAGS = $(WFLAGS) $(DFLAGS) $(GLFLAGS)
LDFLAGS = -export-dynamic -lXext -lX11 $(LGLFLAGS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
.SUFFIXES: .cc
.cc.o:
$(CXX) -c $(CXXFLAGS) $<
.c.o:
$(CXX) -c $(CXXFLAGS) $<
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LDFLAGS)
The function I am trying to call is "drawPloygonLine()". I have declared this in "assignment1gui.h", and the definition, as I mentioned earlier, is in main.cpp.
From all the help on the Internet, I realized that there must some problem with the compile code. But I am not sure. Could someone please help me out?
Sorry I left out this part earlier. The errors I am getting are:
assignment1gui.o: In function `on_btn_color_color_set':
assignment1gui.c:(.text+0x1c): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_line_toggled':
assignment1gui.c:(.text+0x8b): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_circle_toggled':
assignment1gui.c:(.text+0xfc): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_rect_toggled':
assignment1gui.c:(.text+0x16d): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_edit_toggled':
assignment1gui.c:(.text+0x24a): undefined reference to `drawPolygonLine'
collect2: ld returned 1 exit status
make: *** [ass1] Error 1
The C/C++ files I have in the folder are main.cpp, assignment1gui.c and shadertools.c. I also have two header files- assignment1gui.h and shadertools.h. As I have mentioned earlier, I used the assignment1gui.h file to declare the new function "drawPolygonLine();"
Addition:
The declaration of the "drawPolygonLine();" is now in "main.h" and it looks like this:
#ifndef MAIN_H
#define MAIN_H
extern void drawPolygonLine();
#endif /* MAIN_H */
Both main.cpp and assignment1gui.c have "#include "main.h"" at their beginning. The definition of drawPolygonLine() is:
void drawPolygonLine()
{
if(option[opCount-1]==4 && drawn==false)
{
vCount++;
vertex[vCount].x=A;
vertex[vCount].y=B;
lines=lines+2;
vCount++;
vertex[vCount].x=polyX;
vertex[vCount].y=polyY;
clicks=0;
drawn=true;
}
}
All the variables used in the function are global in main.cpp.
An example of how I am calling drawPolygonLine(); in assignment1gui.c is in this function:
void on_btn_color_color_set(GtkColorButton *colorbutton, gpointer user_data)
{
drawPolygonLine();
GdkColor color;
gtk_color_button_get_color(colorbutton, &color);
printf("Color set rgb=(%i,%i,%i)\n",color.red,color.green,color.blue);
}
I hope this makes it clear.

The problem is that main.cpp isn't understood by this make file, since it only has rules for .cc or .c files. I suspect that main.o isn't being built - or, more likely, since you're getting as far as a failed compile, there is another file called main.c or main.cc which IS included in your program, but doesn't have drawPolygonLine() defined in it.
To solve this:
Remove or rename any existing main.c or main.cc files.
If your program is actually a C program, then change the filename to main.c
If your program is a C++ program, you could try changing the extension to .cc, but I suspect you'll then run in to problems since you're using gcc rather than g++. In this case, I'd also change:
CXX = gcc
to
CXX = g++
Remember that although a lot of C code is also valid C++ code, there are many subtle differences - and the best practices are very different in each language. For this reason, it's best to treat C and C++ as different languages.
If this doesn't fix it:
Check that the function signature of drawPolygonLine() declared in your header file is the same as the way it's defined in your main file. Check that these declarations match with the way you've called it.
Check that the files that call drawPolygonLine() have #include "assignment1gui.h" at the top
Check that drawPolygonLine() isn't declared as static (static functions aren't visible outside their translation unit - so the linker won't see them when compiling two output files together)
Also, it's good practice to have the function declaration in the header file corresponding to the source file it's defined in - so if you want to call a function in main.c from assignment.c, you would usually put the declaration in main.h, and #include it at the top of assignment.c. This won't be the cause of the problem that you're having, but it's good practice to get used to.

Related

Compiling error with errors like "multiple definition"

I am trying to compile my C program and I am getting some weird compiling errors and I have no idea where it is coming from. I already found similar posts, but their solution of specifying the output with -o is not working.
SO this is how my makefile looks like (shortened up):
CC = gcc -O3 -Wextra -Wall -pg -g -std=c99
OBJ = ./src/main.o ./src/FUNC.o ./src/getRoot.o ./src/getTree.o
out: $(OBJ)
g++ -std=c99 -g -o ./myProgramm $(OBJ)
./src/FUNC.o: src/FUNC.c
$(CC) -c src/FUNC.c -o ./src/FUNC.o
./src/main.o: src/main.c
$(CC) -c src/main.c -o ./src/main.o
./src/getRoot.o: src/getRoot.c
$(CC) -c src/getRoot.c -o ./src/getRoot.o
./src/getTree.o: src/getTree.c
$(CC) -c src/getTree.c -o ./src/getTree.o
This is a part of the errors i am getting:
./src/FUNC.o:(.rodata+0x78): multiple definition of `khStrInt'
./src/main.o:(.rodata+0x0): first defined here
./src/FUNC.o: In function `get_nbr_edge_kmer':
/home/Documents/EXAMPLE_CODE/src/FUNC.c:126: multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/getRoot.o:(.rodata+0x0): multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/main.o:(.rodata+0x4): first defined here
./src/getTree.o:(.rodata+0x0): multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/getRoot.o:(.rodata+0x0): multiple definition of `khStrInt'
Does someone maybe have some idea what i am doing wrong here :/
Inside your header file, you should declare your variable like:
extern const int khStrInt;
Then in a .c file, you should define it like:
const int khStrInt = 33;
This means the variable definition is only generated once by the compiler when compiling the .c file and so the linker doesn't see multiple definitions. Also, having the declaration in the header file allows other files which include the header to be able to use the variable.
Quite likely the problem is caused by lack of #include guards.
To prevent a file from being included more than once
#ifndef myheader_h
#define myheader_h
#define DISTANCE_MAX 1000
#endif

error makefile C- opengl

I am trying to compile a .c file containing c-code for opengl.
But I keep getting the following error:
Interesting question.
undefined reference to 'glClear'
undefined reference to 'gluLookAt'
undefined reference to 'glLoadIdentity'
undefined reference to 'glColor3f'
undefined reference to 'glLineWidth'
undefined reference to 'glBegin'
undefined reference to 'glVertex3d'
undefined reference to 'glEnd'
etc...
I am pretty sure there is nothing wrong with my source code as it is example code that has been provided to us.
the headers i included:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
How could I fix this issue?
FYI: I am compiling this on ubuntu
Your problem lies here:
my3DTest: clean $(OBJS)
LDOPTS=\
cc -o my3DTest $(CFLAGS) $(OBJS) $(LIBPATH) $(LIBS)
the variable LDOPTS assignment is continued into the next line, due to the backslash (\), thereby your cc command is just assigned to that variable. Once that's done make continues by using its standard implicit target rules to build the binary. But since you didn't specify the linker options in a variable that make will use for that implicit rule, it will try to link without these variables.
Makefile, assuming that the sourcefile is names vlucht.c.
Important Notice: Indentation and whitespace does matter in a Makefile. Improper indentation will corrupt the Makefile!
LDLIBS = -lglut -lGLU -lGL -lXt -lXext -lm
EXE = vlucht
OBJS = vlucht.o
.PHONY: clean
all: $(EXE)
$(EXE): $(OBJS)
clean:
-$(RM) -f $(EXE) $(OBJS)

using a method from another file without including it [duplicate]

This question already has answers here:
Why is #include <stdio.h> not required to use printf()?
(3 answers)
Closed 8 years ago.
I have two .c files which I compile over a makefile.
foo.c:
void foo()
{
printf("this is foo");
}
main.c:
#include <stdio.h>
int main()
{
printf("this is main\n");
foo();
}
the makefile looks like that:
all: main.o foo.o
gcc -o prog foo.o main.o
main.o: main.c
gcc -c main.c
foo.o: foo.c
gcc -c foo.c
So the question is:
how can foo.c use printf() without me including stdio.h AND how can main.c use the method foo() without me including foo.c.
My guess/research is that the makefile works as a linker. But I dont have prove for that and want to understand how this works excactly.
Correct me if I misunderstood something.
In the compilation phase, the compiler checks function calls against prototypes. Any function that lacks a prototype is assumed to return int and to accept any number of arguments.
If you turn up the warning level, gcc will warn you if a prototype is missing. You should add -Wall and you could also add -pedantic to get diagnostics on additional things the compiler think are suspicious.
If the compilation step succeeds, the compiler creates an object file which contains the compiled code and 2 reference tables. The first table is the export table. It contains the names of all functions and variables that are exported from the object file.
The second table is the import table. It contains a list of all functions and variables that are referenced, but where the declaration was missing.
In your case we have:
foo.o:
Export:
foo
Import:
printf
main.o
Export:
main
Import:
printf
foo
In the linker phase, the linker will take the list of imports and exports and match them. In addition to the object files and libraries you specify on the command line, the linker will automatically link with libc, which contains all functions defined by the c language.
In the makefile you can force the complier to include <stdio> or any other header:
From the docs:
-include file
Process file as if #include "file" appeared as the first line of the
primary source file. However, the first directory searched for file is
the preprocessor's working directory instead of the directory
containing the main source file. If not found there, it is searched
for in the remainder of the #include "..." search chain as normal. If
multiple -include options are given, the files are included in the
order they appear on the command line.
Just add -include filename.h in the GCC/compiler command line within the makefile.
The makefile is not a linker. It is input to make. The makefile just tells make what commands to execute under what conditions.
Your all target is running gcc in linking/linker mode gcc -o prog foo.o main.o.
The same way your foo.o and main.o targets are running gcc in compilation mode gcc -c foo.c.
For the record you can combine the two .o targets into just
%.o: %.c
gcc -c $^
which is, in fact, already a default rule in make so you need not include that rule at all.
Additionally your all target is not following bet make practices because it generates a file that does not match the name of the target. So you should use
all: prog
prog: main.o foo.o
gcc -o prog foo.o main.o
instead.
Though once again there make has you covered by default and so your entire makefile can be replaced by
all: prog
prog: main.o foo.o
and you should get the same results.

Linking error: Undefined reference to functions that're defined in a separate file?

I'm probably forgetting something obvious that'll solve this. While there's other questions on SO with the same issue, none of the solutions have been applicable to my situation.
I have a main file, sim.c, a header file net.h, a header file friends.h, and a file with the functions, net.c. I have a makefile, which I created with gmakemake > Makefile, and its contents are very basic.
Header.mak (makefile template):
CFLAGS = -Wall -Wextra -pedantic -std=c99 -ggdb
LFLAGS = -ggdb
LDFLAGS =
Makefile relevant contents:
CPP_FILES =
C_FILES = net.c sim.c
PS_FILES =
S_FILES =
H_FILES = net.h friends.h
SOURCEFILES = $(H_FILES) $(CPP_FILES) $(C_FILES) $(S_FILES)
.PRECIOUS: $(SOURCEFILES)
OBJFILES =
#
# Main targets
#
all: net sim
net: net.o $(OBJFILES)
$(CC) $(CFLAGS) -o net net.o $(OBJFILES) $(CLIBFLAGS)
sim: sim.o $(OBJFILES)
$(CC) $(CFLAGS) -o sim sim.o $(OBJFILES) $(CLIBFLAGS)
#
# Dependencies
#
net.o: net.h
sim.o: net.h
My sim.c file contains:
#include "net.h"
#include "friends.h"
My header file contains the functions in net.c and defines them all as stubs. I copied and pasted them to create the function headers, so there shouldn't be any typos.
My net.c file contains:
#include "net.h"
Yet any time a function in sim.c tries to call a function in net.c, it errors on that line with:
"undefined reference to `function_name`".
How can I make sim.c able to access the functions in net.c?
The message undefined reference to 'function_name' implies that of all the object files you're giving to the linker, none of them has a definition for function_name. That means that either
You're not linking with net.o
net.c (as compiled) does not contain a definition for function_name -- by 'as compiled' I mean with all of the various preprocessor options you use on it.
Since you show neither your link command line nor the contents of net.c, we can't tell which is the problem.
edit
with your edit, we can see clearly that you have the first problem -- when you try to link sim, you do not include net.o on the link command line. Most commonly, you would link sim with a makefile entry like:
sim: sim.o net.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LDLIBS)
or more simply just:
sim: sim.o net.o
relying on the default make actions for linking object files
For the two functions "see" each other make sure that:
Both c/cpp files are included in the makefile
Both definition(c/cpp) and declaration (h) files contains the same definition of the function: name/params/return value
The function being called must not be static.
Make sure you don't declare (or include) the same type with different structure in the source files.
That should do, unless you are using a very old complier with even more evil things that can go wrong ;)

Figuring out multiple file compilation with make & C

For a project, I was working with a partner writing a decision tree implementation. Since both of us are relative newcomers to C and had to work quickly, we basically dumped all the functionality in a single file, which ended up being over 1600 lines. It was a quick and dirty project to get working, but now the next assignment has us responsible for extending and re-implementing the code. In its current condition, that isn't going to happen.
Right now, I'm breaking up the original source based on function responsibility. Thing is, many of the functions are intertwined, and I'm getting major errors with my make file. More specifically, the other source files are reporting implicit declaration of functions that are declared in a separate file.
I really have no experience with multiple file makefiles. The current syntax is borrowed from a simple shell implmentation in last years Systems Programming class, although this current project is an order of magnitude greater in complexity.
cc= gcc
CFLAGS= -g -Wall -lm
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o proj2 main.o split.o tree.o id3.o output.o
I also tried a previous version where each object file was compiled separately like
main.o: main.c split.c tree.c id3.c output.c
$(CC) $(CFLAGS) -o main.c split.c tree.c id3.c output.c
and this repeated to create a .o file for each source, which then was compiled into an executable.
However, that didn't work and I got about 500 lines of compiler complaints and warnings, mainly about implicit function declarations.
So, essentially I have two related questions:
is it possible to intertwined function calls between different source files?
if so, how can I make it possible here?
First a word about your makefiles.
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o proj2 main.o split.o tree.o id3.o output.o
This should work (if the code is correct) but if you're using GNUMake (which you should) you can tidy it up:
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o $# $^
Now you have only one copy of the object list to maintain.
The other version is just wrong:
main.o: main.c split.c tree.c id3.c output.c
$(CC) $(CFLAGS) -o main.c split.c tree.c id3.c output.c
First, you're trying to compile all of the source files into one object file, which kind of defeats the purpose of object files. Second, you're naming your one object file main.o when that name should really belong to an object file made from main.cc. Third, the command tells the compiler to compile all of the other source files (split.c, tree.c, ...) into an object file called "main.c"-- not illegal, but you're bound to trip yourself up.
Also, you should try to use C++, not C, but that's for another day.
Now for breaking up the Big Ball of Mud. I assume you know how to break big functions into smaller ones, so the problem is segregating functions into different source files (and then compiling and linking them correctly). Suppose main() calls a function foo():
/* main.c */
void foo()
{
// do foo things
}
int main()
{
// do main things
foo();
return(0);
}
As you know, the foo must come first, otherwise the compiler would balk when main tried to call an undeclared function. But we can declare foo beforehand:
/* main.c */
void foo();
int main()
{
// do main things
foo();
return(0);
}
void foo()
{
// do foo things
}
When the compiler reaches the call to foo(), it already knows that such a function exists, and trusts us to define it later. Now here's the trick: if we instruct the compiler to compile, but not link (that is, produce an object file like main.o, not an executable like proj2), it will trust us even farther:
/* main.c */
void foo();
int main()
{
// do main things
foo();
return(0);
}
That will compile into main.o quite nicely. The compiler trusts us to provide the definition of void foo() in some other object file when we link things together into an executable. The definition will be in another file like so:
/* foo.c */
void foo()
{
// do foo things
}
We could build this by hand:
gcc -g -Wall -lm -c foo.c -o foo.o
gcc -g -Wall -lm -c main.c -o main.o
gcc -g -Wall -lm foo.o main.o -o proj2
But that gets tedious fast, so we'll write a makefile:
cc= gcc
CFLAGS= -g -Wall -lm
proj2: main.o foo.o
$(CC) $(CFLAGS) -o $# $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
So far so good. If this much is clear then we can move on to header files...
You need to create header files for each of the source code to have the declarations in them. You then #include the appropriate header files at the top of the source code.

Resources