Calling a C function defined in another file - c

I know this question has a lot of answers, but I am always getting an error on gcc c1.c
c1.c:(.text+0x5): undefined reference to `f'
collect2: error: ld returned 1 exit status
no matter what I try.
This is c1.c
#include <stdio.h>
#include "c.h"
int main()
{
printf("F %d\n",f());
}
THis is c2.c
#include <stdio.h>
int f(void) {return 7;}
int main()
{
printf("S %d\n",f());
}
This is c.h
int f(void);
How could I get it working? Actually, I was getting this error in a big program that is modelled like this. I guess this is the way to do it.
(And yes, main should return 0).

You're going to have problems, since you have two different main functions defined, but the general way to do this is a link-time issue:
gcc -c c1.c
gcc -c c2.c
gcc c1.o c2.o
All you need to do is figure out which main you want, and remove the unwanted one.
You could do something like:
gcc -Dmain=blah -c c1.c
gcc -c c2.c
gcc c1.o c2.o

Related

Can I define a C extern function required by a library without an extra compilation step?

I have been provided a library a that expects there to be a function b() but does not implement it. It looks like this (I can't change this code):
a.h:
void a();
a.c:
#include "a.h"
extern void b();
void a() {
b();
}
The library was compiled like this (assume all files in these examples are in the same directory for simplicity).:
gcc -shared a.c -o liba.so
I want to call a() in my code, so I write a program that looks like this:
main_v1.c:
#include "a.h"
int main(void) {
a();
return 0;
}
If I try to compile this, I'll get a linker error because b() hasn't been defined:
gcc main_v1.c -L ./ -la -o main
.//liba.so: undefined reference to `b'
collect2: error: ld returned 1 exit status
The simplest thing I can do is add a definition of b() right in my main.c:
main_v2.c:
#include <stdio.h>
#include "a.h"
void b() {
printf("b");
}
int main(void) {
a();
return 0;
}
gcc main_v2.c -L ./ -la -o main
This works. But what if I don't want to define b() in my main.c? For example, if I want to be able to re-use my b() implementation elsewhere? One think I know I can do is compile it into a second library and link against it, like this:
b_v1.c:
#include <stdio.h>
void b() {
printf("b");
}
gcc -shared b_v1.c -o libb.so
gcc main_v1.c -L ./ -la -lb -o main
This works too. Note that -lb must come after -la; it won't work the other way around.
But I'd really like to avoid compiling another library. Why can't I just do this?:
b.h:
void b();
b_v2.c:
#include <stdio.h>
#include "b.h"
void b() {
printf("b");
}
main_v3.c:
#include "a.h"
#include "b.h"
int main(void) {
a();
return 0;
}
gcc main_v3.c -L ./ -la -o main
This doesn't work. I get the same linker error:
.//liba.so: undefined reference to `b'
collect2: error: ld returned 1 exit status
Why not? How is this different from my first working example in main_v2.c? Is there a way to accomplish this without creating a separate library for b()?
As Mat pointed out, I was simply neglecting to include the b_v2.c source in the compilation step. This works:
gcc main_v3.c b_v2.c -L ./ -la -o main
How is this different from my first working example in main_v2.c?
In version 3, no implementation of b() is even compiled, much less linked into the final executable. A declaration alone is not sufficient, and including a header is completely independent of compiling or linking an associated source file.
Note that your a.c has exactly as much of a declaration of b() as main_v3.c acquires from b.h, so if nothing in main_v3.c calls that function, then that header is not adding anything new or useful.
Is there a way to accomplish this without creating a separate library for b()?
Sure, several. But the easiest one for you to use might be to just name both your C source files on the same compilation command line:
gcc main_v1.c b.c -L. -la -o main
Note that I have chosen main_v1 intentionally: since nothing in the file calls b(), it is not useful for a declaration of that function to appear in the file, whether directly or via header inclusion.
a.h
void a();
a.c
void b();
void a() {
b();
}
b.c
#include "a.h"
#include <unistd.h>
void b()
{
write(1, "test", 4);
}
compile
$> gcc *.c
exec
$> ./a.out

GCC Error but VS no error

When I compile the below program it is giving me this error.
/tmp/ccwr6gsJ.o: In function 'main':
main.cL(.text+0xa): undefined reference to 'example'
collect2: error: Id returned 1 exit status
Main.c:
#include <stdio.h>
#include "includes.h"
int main()
{
int exampleInt = example();
return 0;
}
includes.h:
int example();
includes.c:
#include "includes.h"
int example()
{
int i = 3;
return i;
}
It seems to work in Visual Studio but not on GCC on Linux
This is very likely a build error, i.e. you're calling the compiler on the wrong set(s) of files, and/or not doing a linking step.
Try:
$ gcc -o myprog main.c example.c
Note that a mere #include in a C file does not in any way tell the compiler to compile more C files.

netfilter queue undefined reference to `nfq_open'

I have writting this code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/netfilter.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
int main(int argc, char **argv)
{
struct nfq_handle *h;
printf("opening library handle\n");
h = nfq_open();
nfq_close(h);
exit(0);
}
and when I try to compile it says that:
/tmp/ccEv9MYS.o: In function `main':
test1.c:(.text+0x1a): undefined reference to `nfq_open'
test1.c:(.text+0x2a): undefined reference to `nfq_close'
collect2: ld returned 1 exit status
I tried checking if the library is found by gcc and it is (when I modifiy the incluse of libnetfilter_queue there is an error), I recompiled the library and made sur that the fonctions I'm calling are in in it.
If you have any clue thanks for helping
Icompile using this:
gcc -o test test1.c
I have also tried:
gcc -o test -lnetfilter_queue test1.c
gcc -o test -L/usr/local/lib test1.c
Well, from the gcc manual page, for the -llibrary linking option
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
That says, the linker works from left to right, so need to put the dependent on left hand side.
You need to change your compilation statement to
gcc -o test test1.c -lnetfilter_queue

Trouble using makefile with multiple files in C

Starting to get my head around makefiles for my C programs, but having some trouble when trying to include multiple files. Ignoring the fact that the program below is incomplete (in terms of functionality but not compilation), I'm trying to get this program compiling and running using a make file.
Here is my make file:
main: main.o IntList.o
gcc -o main main.o IntList.o
main.o: main.c
gcc -c -ansi -pedantic -Wall main.c
IntList.o: IntList.c IntList.h
gcc -c -ansi -pedantic -Wall Intlist.c
And here is the error I am receiving:
gcc -c -ansi -pedantic -Wall Intlist.c
gcc -o main main.o IntList.o
ld: duplicate symbol _getNewInt in IntList.o and main.o
collect2: ld returned 1 exit status
make: *** [main] Error 1
The code for the program is below. I'm not sure whether it's the make file or my includes in the program files that are causing problems (or both!)
Any help would be great. Cheers.
Edit: Any tips to steer me in the right direction in terms of modularization would be much appreciated as I'm not sure if I am doing this the best way.
IntList.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Constants */
#define MAX_INTS 10
/* Signed ints can have a maximum of 10 digits. We make the length 11 to
* allow for the sign in negative numbers */
#define MAX_INPUT_LENGTH 11
#define EXTRA_SPACES 2
/* Typedefs / Structs */
typedef struct {
int list[MAX_INTS];
int noInts;
} IntList;
/* Proto Types */
int insertIntToList(int *list);
void shiftList(int offset);
void displayList();
IntList.c
#include "IntList.h"
int getNewInt(int *list)
{
int valid = 0, inputInt;
char inputString[MAX_INPUT_LENGTH + EXTRA_SPACES];
while(!valid)
{
printf("Input an int: ");
valid = 1;
if((fgets(inputString, MAX_INPUT_LENGTH + EXTRA_SPACES, stdin)) != NULL)
{
sscanf(inputString, "%d", &inputInt);
/* Check first that the input string is not too long */
if(inputString[strlen(inputString) - 1] != '\n')
{
printf("\nError: Too many characters entered \n");
valid = 0;
}
printf("\nThe Int: %d", inputInt);
printf("\n");
}
}
}
void shiftList(int offset)
{
}
void displayList()
{
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "IntList.c"
int main(void)
{
int intList[10];
getNewInt(intList);
return EXIT_SUCCESS;
}
Don't include the .c file in main, include the .h file. Otherwise the code in IntList.c gets compiled both into the IntList.o and the main.o, so you'll get duplicate symbols.
Use this in main.c instead of IntList.c:
#include "IntList.h"
#include "IntList.c"
should be:
#include "IntList.h"
Also (though nothing to do with your problem) I would recommend not using mixed case in the names of source files, as it can lead to portability problems and hard to diagnose "no such file" errors - use all lower case, like the standard library headers do.
Don't #include "IntList.c" into main.c
You should not have:
#include "IntList.c"
in your main program, it should be:
#include "IntList.h"
By including the C file, you create a getNewInt in both your main and IntList object files, which is why you're getting the duplicate definition error when you try to link them together.
main.c should include "IntList.h", not "IntList.c".
If you include IntList.c, the functions in IntList.c will be implemented both in IntList.o and in main.o, which would produce the "duplicate symbol" error you're seeing.
As others have mentioned, you include .h files, not .c files
Also when you compile, you only compile .c files so you should remove any references to .h files in your Makefile

Include a source file in a C program

How can I include foo() function of foo.c in this small program (sorry for my noob question):
In my foo.h file:
/* foo.h */
#include <stdio.h>
#include <stdlib.h>
int foo(double largeur);
In foo.c:
/* foo.c */
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int foo(double largeur)
{
printf("foo");
return 0;
}
And in main.c:
/* main.c */
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int main(int argc, char *argv[])
{
printf("Avant...");
foo(2);
printf("Apres...");
return 0;
}
After compiling:
$ gcc -Wall -o main main.c
I get this error:
Undefined symbols: "_foo",
referenced from:
_main in ccerSyBF.o ld: symbol(s) not found collect2: ld
returned 1 exit status
Thanks for any help.
$ gcc -Wall -o main main.c foo.c
GCC doesn't know to look for foo.c if you don't tell it to :)
Creating a program in C requires two steps, compiling and linking. To just run the compiling part, use the -c option to gcc:
gcc -c main.c
This creates an object file, main.o (or main.obj on Windows). Similarly for gcc -c foo.c. You won't get the error message above at this stage. Then you link these two object files together. At this stage, the symbol foo is resolved. The reason you got the error message was because the linker couldn't find the symbol, because it was only looking at main.o and not foo.o. The linker is usually run from gcc, so to link your object files and create the final executable file main, use
gcc -o main main.o foo.o
You have to compile foo.c also because it is another module. Let me see how they do it in gcc:
$ gcc -Wall main.c foo.c -o main
You could also do this in your MakeFiles, like this:
APP_NAME = Foo
Foo_HEADERS = foo.h
Foo_FILES = main.c foo.c
If you're not so much familiar with MakeFiles i suggest you to take a look at Make Docs, but this is a simple example, APP_NAME sets the name of the compiled executable(in this case is Foo), Foo_HEADERS will set the headers used by your application, Foo_FILES you will set the source files of your applications, remember to put the APP_NAME(in this case Foo) at the beginning of _HEADERS and _FILES. I suggest you to use MakeFiles because they will organize you application build process and will be better for the end-user.

Resources