Using external functions in C - two .c files - c

I am using net beans, and am trying to define function in an external C file, and use them in my main C file. It seems like the linker isn't working or something, as I am getting a build error:
undefined reference to `setPixel'
The file containing my functions is myLib.c. The file that I am calling the function in is main.c
Both of these files #include myLib.h which contains the function prototypes for the functions within myLib.c
I shouldn't be getting this error, any ideas?

What does your compile command look like? Obviously myLib.c will need compiling or the link will fail..
gcc main.c myLib.c

Related

Using a function from another C file placed in another directory?

Say I have a parent directory A with two subdirectories B and C.
Sub-directory C has a helper.c and helper.h as shown:
//helper.c
void print(){
printf("Hello, World!\n");
}
//helper.h
void print();
Now, in sub directory B, I have a main.c which just calls the print function:
//main.c
#include<stdio.h>
#include"../C/helper.h"
void main(){
print();
}
I tried the following commands for compiling main.c:
Command 1: gcc main.c //Gives undefined reference to 'print' error
Command 2: gcc main.c ../C/helper.c //Compiles successfully
Now I removed the #include"../C/helper.h" from main .c and tried the Command 2 again. It still works.
So I have the following questions:
i) What difference does it make whether the helper.h file is included or
helper.c?
ii) Why command 1 fails?
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
What happens when you execute:
Command 1: gcc main.c //Gives undefined reference to 'print' error
When execute gcc main.c
Compiler compiles main.c and creates objective file. This file will contain unresolved link to function print(). Because there is no implementation of function print() in main.c file.
After compilation gcc tries to make full executable file. To do this gcc combines all objective files and tries to resolve all unresolved links. As you remember there is unresolved link for function print(), gcc can't find implementation and raise the error.
When you execute
Command 2: gcc main.c ../C/helper.c //Compiles successfully
gcc compiles both files. Second file ../C/helper.c contains implementation of function print(), so linker can find it and resolve reference to it in function main().
i) What difference does it make whether the helper.h file is included or helper.c?
In your case helper.h contains forward declaration of function print(). This gives information to compiler how to make call of function print().
ii) Why command 1 fails?
See above.
iii) Is there a way to compile my C program without having to specify helper.c everytime?
Use make utility. Compile helper.c in separate objective file helper.o and use it in linkage command.
helper.o: ../C/helper.c ../C/helper.h
gcc -c ../C/helper.c
main.o: main.c main.h
gcc -c main.c
testprog: main.o helper.o
g++ main.o helper.o -o testprog
See make utility manual for details.
Commands should be indented by TAB.
First you need to understand that #include simply adds whatever text is in the #include parameter to the position in the file the statement is in, for example:
//file1.h
void foo();
//main.c
#include "file1.txt"
int main(int argc, char **argv)
{
foo();
return 0;
}
Will cause the pre-compilation to generate this unified file for compilation:
//main.c.tmp
void foo();
int main(int argc, char **argv)
{
foo();
return 0;
}
So to answer your first and second questions:
When you include a header file (or any file) that only contains declarations (i.e function signatures) without definitions (i.e function implementations), as in the example above, the linker will fail in finding the definitions and you will get the 'undefined reference' error.
When you include a c code file (or any file) that contains definitions, these definitions will be merged to your code and the linker will have them, that's why it works.
and as for your third question
It is bad practice to include c files directly in other c files, the common approach is to keep separate c files with headers exposing the functionality they provide, include the header files and link against the compiled c files, for example in your case:
gcc main.c helper.c -o out
Will allow you to include helper.c in main.c and still work because you instructed the compiler to compile both files instead of just main.c so when linking occurs the definitions from the compilation will be found and you will not get the undefined behavior error
This is, in a nutshell. I abstracted a lot of what's going on to pass on the general idea. this is a nice article describing the compilation process in fair detail and this is a nice overview of the entire process.
I'll try to answer:
i) What difference does it make whether the helper.h file is included or helper.c?
When you include a file, you don't want to expose your implementation, hence its better to include h files, that contains only the "signatures" - api of your implementation.
ii) Why command 1 fails?
When you compile you must add all your resources to the executable, otherwise he won't compile.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can use Makefile to compile your program. Maybe this tutorial can help you.
i) What difference does it make whether the helper.h file is included
or helper.c?
Including helper.c means that helper.c gets compiled each time as if it were part of main.c
Including helper.h lets the compiler know what argument types the function print() takes and returns so the compiler can give an error or warning if you call print() incorrectly
ii) Why command 1 fails?
The compiler is not being told where to find the actual code for the print function. As explained, including the .h file only helps the compiler with type checking.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can compile it once into an object file and optionally you can add that obj to a static or dynamically loaded library. You still need to help the compiler find that obj or library. For example,
gcc -c helper.c
gcc main.c helper.o
The correct way to avoid compiling modules that don't need compiling is to use a Makefile. A Makefile compares when a module was last compiled compared to when it was last modified and that way it knows what needs to be compiled and what doesn't.

How to organize Header files

Using header files in this way gives me the error "undefined reference to somefunc". What is the proper way to make sure somefunc.c is seen so this error doesn't occur? It seems simply including somefile.h in main.c isn't enough to see the definitions in somefile.c
main.c
#include "somefile.h"
int main() {
somefunc();
return 0;
}
somefile.h
#ifndef SOMEFILE_H
#define SOMEFILE_H
void somefunc();
#endif
somefile.c
#include <stdio.h>
#include "somefile.h"
void somefunc() {
printf("hello\n");
}
I don't understand why I am getting errors because this is the same manner in which they are used in tutorials and videos i've been viewing while looking for an answer. The code above is an answer given earlier but it is still has the same error.
Undefined reference to somefunc is a linker error, not a compiler error.
This means that, although when compiling main.c the header somefile.h is found, you are not compiling the file somefile.c together with main.c. So when linking occurs the linker is not able to find the implementation of somefunc in any object file to resolve the call from main().
If you are using GCC or Clang just compile both source files to your command, eg
gcc somefunc.c main.c -o output
If you are using an IDE instead, make sure that somefile.c is compiled together with main.c when building the application.
This doesn't appear to be a problem with the header file.
This appears to be a problem in linking, which depends on how you build the project. If you use an IDE, it means that somefile.c is not included in the project. If you're using make and a makefile, it means that somefile.c is not listed in the makefile, or at least not included for the linker. If you're building at the command line (not using make or some build tool, but using gcc), then you're not including somefile.c in the command.
The undefined reference error means the linker couldn't find the code in somefile.c, because the linker didn't know to include it.

Building object files that depends on other object files

EDITS: Including link to my makefile
I have a main program that calls a bunch of functions defined in other source files. This is not a problem because I am using cc -c functionSource.c functionHeader.h and generating object files before compiling my main program with cc main.c func1.o func2.o .... -o test.o
I am having problems when one of my functions depends on another function.
For example:
My main program calls an shuffle function which is defined in it's own source file and the shuffle function calls a swap function which in turn is defined in it's own source file.
When i try to generate the shuffle.o file for my main program using cc -c shuffle.o I get an undefined reference to swap error.
When I try to cc shuffle.c swap.o i get an undefined reference to main error.
Here is my makefile
How do I go about fixing this?
Found the problem. I had a swap function declared inside insertionSort.h and shuffle.h but no implementations.
Have a look to the man page: '-c' makes the compiler generating object files only (not trying to link).
Do the following:
cc -c insertionSort.c # => gives insertionSort.o
cc -c -c functionSource.c # => gives functionSource.o
cc insertionSort.o functionSource.o ...and-so-on... main.c -o test
It's not necessary to specify header files - it doesn't help.
BTW: If you have mor than one implementation file, it is rather useful
(a) to learn make
(b) stick to the convention that object files and programs should be named like th sources.
E.g:
foo.c => foo.o
bar.c => bar
etc - you get the picture.
This has nothing to do with make. You need to get a book on introductory C programming, that will explain how to use the preprocessor, and you need to examine the documentation for your compiler so you understand what the different compiler flags do (such as when you want to use the -c flag and when you don't, and what the difference is).
It's wrong to include header files (.h files) on the compile line. Only source files (.c) should be included on the command line when building object (.o) files. You should be adding the headers you need into your .c files using the #include directive: #include "insertionSort.h". If you're missing a reference to a function, then #include the header file that declares that function: #include "swap.h".

Compiling with gcc including .h files?

I'm trying to compile some AES implementation code from http://www.efgh.com/software/rijndael.htm, I got a txt file and splitted it up so I got 3 files:
encrypt.c
decrypt.c
rijndael.h
Having all this 3 files in the same folder, I try to compile any of encrypt.c or decrypt.c files but it throws some errors about undefined functions which actually are in rijndael.h
I'm performing compilation this way:
gcc -o encrypt encrypt.c or gcc -o decrypt decrypt.c
And I get:
/tmp/cch6JvXT.o: In function main:
encrypt.c:(.text+0x127): undefined reference to rijndaelSetupEncrypt
encrypt.c:(.text+0x1c6): undefined reference to rijndaelEncrypt
collect2: error: ld returned 1 exit status
But rijndaelSetupEncrypt and rijndaelEncrypt are in the rijndael.h file
There is a difference between an "undeclared function" error and an "undefined function" error. The first one is given when it can not find the prototype (meaning only the function header) of a function you've used, prototypes being usually put in the .h files and included in your .c files. The second error appears when it finds the prototype but not the definition of the function. The definition of a function (meaning the entire body of a function) can be fount either in a library or in another .c file that you should add to your compile command.
For "undefined function" error you could try
gcc -o enc_dec encrypt.c decrypt.c
if the function it cannot find is in one of the two .c files you've mentioned.
If it's not, you might have forgotten to link a library.
Later edit:
With the rijndael.c file:
gcc -o decrypt rijndael.c decrypt.c
gcc -o encrypt rijndael.c encrypt.c
It doesn't matter if rijndael.h hasn't got a main function. I suppose it has definitions for some of the functions used in decrypt.c and encrypt.c
Actually in your example, you should have 4 files, encrypt.c decrypt.c rijndael.c and rijndael.h
So you have to compile rijndael.c and encrypt.c or same with decrypt together. .h files will be automatically used during compilation of c file which included the .h (header) file.

How are you intended to include files in a C project?

I have three files.
trees.h
// a bunch of typedefs and function prototypes
#include <trees.c>
trees.c
// a bunch of function bodies
main.c
#include <trees.h>
This isn't right, because every function in trees.c is giving me "undefined type" errors about the type defined in trees.h. I've tried every configuration I can think of - include trees.c from main and include trees.h from trees.c, include trees.c at the end of trees.h, include it at the beginning of trees.h... Every combination of includes I could think of, and each one gives a different set of errors. Sometimes it's multiple defines, sometimes it's undefined functions...
So how exactly does this work? What do I put in which files, and which files do I include and where?
Like this:
trees.h
// a bunch of typedefs and function declarations (prototypes)
trees.c
#include <trees.h>
// a bunch of function definitions (bodies)
main.c
#include <trees.h>
Explanation:
#include is basically the same as copying the entire included file to this file (where you put the #include).
So including trees.h in main.c allows that file to know about functions in trees.c.
Including trees.h in trees.c allows functions lower down in trees.c to be usable and this is also where defines, etc. used in trees.c is specified.
You also may not know about creating multiple objects and linking them, refer to Joachim Pileborg's answer.
The (very ugly) alternative is:
trees.h
// a bunch of typedefs and function declarations (prototypes)
trees.c
#include <trees.h>
// a bunch of function definitions (bodies)
main.c
#include <trees.c>
Then you just need to compile main. But for any project of a few .c files, this becomes impractical.
You compile each source file into object files, then link these object files together to form the final executable. If you use e.g. GCC and compile on the command line you can put both source files in the command line and GCC will handle it for you:
$ gcc main.c tree.c -o tree
The above command tells gcc to compile and link the files main.c and tree.c, and name the output executable tree. You can also compile the source file separately into object files, and then manually link them together:
$ gcc -c main.c -o main.o
$ gcc -c tree.c -o tree.o
$ gcc main.o tree.o -o tree
In the above commands, the -c option tells gcc to create an object file, and the -o option tells gcc what to name that object file. The last command takes these object files and create the final executable and names it (with the -o option) tree.
In the source files, you include the header(s) needed, not the other way around.
The reason it's not working is because you have to use 'extern' to define a variable or function that is declared in a different include file to the standard ones. You should also save all header files as *.h. So, assuming you had defined the struct 'tree' in tree.h:
#include <tree.h>
int main() {
extern tree; /* Get variable 'tree' declared in tree.h */
extern make_tree(void); /* Get function make_tree() declared in tree.h */
make_tree(); /* Call function */
return (0); /* End */
}
Begin with not including implementation (.c) files. Only include header (.h) files. Include them whenever you need the types or functions declared in them. To avoid multiple declarations, use include guards (whatever they are - just google it).
The way to go is including your header file trees.h in trees.c and then including trees.c within main.c
Have a look at this thread here

Resources