Undefined reference error in C using Code::Blocks IDE - c

I'm trying to set up some .c files to make it easier on me to find things, once it starts becoming larger. I'll be using SDL calls in the program, hence the includes.
Here's how my main.cpp looks right now:
#include <stdio.h>
#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include <SDL_ttf.h>
#include "WriteText.h"
int main(int argc, char *argv[])
{
int i =0;
i = b();
return 0;
}
In my WriteText.c I have:
#include "WriteText.h"
int b(void)
{
return 3;
}
Finally my WriteText.h:
#ifndef WRITETEXT_H_INCLUDED
#define WRITETEXT_H_INCLUDED
int b(void);
#endif // WRITETEXT_H_INCLUDED
Trying to compile it, I get an undefined reference to 'b()'. I have no idea why this is happening, I practiced it in some basic example codes and everythin works just fine, but as soon as I'd actually use it for something practical I hit an error like this.

The problem is that you are not linking the WriteText.c into your executable. If you gave some more information about how you are creating the executable we could probably give better help.

Chances are your compilation isn't using the writetext object file. Assuming *nix and gcc, your makefile should look something like:
all: myprog
myprog: myprog.o writetext.o
gcc -o $# $^
myprog.o: myprog.cpp
writetext.o: writetext.cpp

I figured out my issue, my main file was .cpp and used CPP compiler (because it was an SDL project), but the new file I added was .c and used C compiler, when I added a new .cpp file and just copy-pasted my code into it, everything worked smoothly.
(I'm not sure if it's "bad form" to write C code in .cpp files but if I intend to use SDL I guess that's the only way to go.)

Related

CLion not finding header in main.c for use in external .c file

So my situation is something like this, I have three files:
main.c:
#include <stdio.h>
#include "hello.h"
int main() {
hello();
}
hello.h:
void hello();
hello.c:
void hello() {
printf("Hello");
}
My Cmake file looks something like this:
cmake_minimum_required(VERSION 3.3)
project(test)
set(SOURCE_FILES main.c hello.c)
add_executable(test ${SOURCE_FILES})
The code runs fine. However CLion doesn't recognise the printf() function in hello.c, and wants me to add it as a header file. Is there a way to make it see the #include <stdio.h> in the main.c file, and stop giving me a hard time?
So I fixed this to my own satisfaction by making the functions defined in my .c files return values rather than calling printf inside those functions. Then printing the values returned in main.c
hello.c and main.c are independent compilation units and as such needs to have #include <stdio.h> in both. Actually in your example having #include <stdio.h> in main.c accomplishes nothing as nothing forward declared there is being used in hello.h nor main.c.
You should actually be seeing warnings when compiling hello.c on its own.
When the compiler finds a function it does not know (has not been declared yet), it assumes it has the signature int function_X(void). So for your case it will be wrong for printf which has int printf(char const*, ...). But you are lucky, due to the way that arguments are passed in your platform, everything works out.
So you basically need to forward declare functions to ensure that when compiling the compiler knows where to place the arguments so that the called function can find it.
There is more to it but this short explanation should be enough for a beginner and if you read one of the books in the link I provided in the comments you should be able to understand it better.

How to use PlaySound in C

I am using code::blocks IDE which runs on GNU GCC compiler. In my project I want to play a .wav sound file in C. I tried to play a .wav sound file with a function called PlaySound. When I compiled the code code::blocks gave me an error - PlaySoundA not declared. My code is-
#include <stdio.h>
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
int main(int argc, char *argv[])
{
PlaySound("C:\Snakes and Ladders\snake.wav",NULL,SND_SYNC | SND_LOOP | SND_FILENAME);
return 0;
}
I checked my path twice. I read about this function on the internet and as per me I am using it in the correct way.
In Google, I read that the function exists in a file called winmm.lib. So I put a line of code after all the headers. It was-
#pragma comment (lib , "winmm.lib")
I also added the name winmm.lib to the additional dependencies of code::blocks. So now when I compile the code it gives me another error - winmm.lib not found. Can somebody please tell me how to use PlaySound correctly.
Remove the pragma comment
Double the backslashes. The backslash is an escape character
Compile with the winmm library. Using MinGW, the command would look like this:
gcc foo.c -o foo.exe -lwinmm
Go to Settings - compiler... - linker settings. on the right side in other linker option write this:-lwinmm

How to include Yacc/Bison-Parser into own project?

I'd like to use the yacc/bison parser for my own project.
When building the Parser with my own Makefile, everything works fine. I took the sources from http://ymorin.is-a-geek.org/projects/kconfig-frontends (just the parser that's: /<path-to-kconfig>/libs/parser.
Now when including these files into the C++ project in Eclipse, after hitting make, the compiler crashes at the .y file, because of a syntax error - wasn't able to read the .y - syntax. So I excluded the parser from the building process.
In the answer of Yacc and Lex inclusion confusion, I've read that only the .h files have to be included, to use the functions of the parser.
So what I did is:
To get access to the parser sources out of my project, I created a simple function that just prints a line on the console in yconf.y and yconf.c: void testout(char *txt) {printf(txt);}
I even created a yconf.h with the function-head void testout(char *txt);
compiled the parser with my own makefile
the main, where I'd like to call the function looks like:
#include "y.tab.h"
#include "yconf.h"
#include <stdio.h>
extern "C"{
int main(int argc, char *argv[])
{
char configIn[] = "test";
printf(configIn);
testout(configIn);
return 0;
}
}
The error
And now when compiling, an error appears: undefined reference to 'testout(char*)'. But Eclipse itself can resolve the function - when clicking that function, the yconf.h opens. And that's why I don't know where exactly the problem is.
Eclipse Settings:
In /project/properties/C/C++ Build/Settings I put the same include paths to the parser-sources for gcc and g++ and the linker. Additionally I added in this settings as "Include files" the y.tab.h and the yconf.h
If more information are needed, please ask.
I appreciate any advises about how to solve this problem. Thanks for the support
Kind Regards
Okay one really just need the y.tab.h and y.tab.c. That is created with this makefile:
lex ./lconf.l
bison -d -y ./yconf.y
My error was: I was programming in C++ and I had the extern "C" command at the wrong place, that header file needs to be declared as c format. Here's the right code:
extern "C"{
#include "y.tab.h"
}
int main(int argc, char *argv[])
{
char configIn[] = "test";
testout(configIn);
return 0;
}
(testout is a function in y.tab.h/c with a simple printf of the parameter configIn - when executing "test" was printed.)
BTW: I excluded all source files of the parser for compilation but of the y.tab.c

How to link two source files properly? undefined reference error

Ok so I am doing a final project for one of my classes and trying to do a bit extra and create multiple files to work with. I am coding inside of CodeBlocks. So far I have a main.c, levels.c, and levels.h for my files. Inside of the levels.c levelOne function, I put the printf statement as a test to make sure I could have the two files work with each other before I went forward in my coding. I got a "undefined reference to 'levelOne' when I compiled and ran the program.
Inside my main.c file:
#include <stdio.h>
#include <stdlib.h>
#include "levels.h"
int main()
{
levelOne();
return 0;
}
Inside my levels.h file:
#ifndef LEVELS_H_INCLUDED
#define LEVELS_H_INCLUDED
void levelSelect(char c);
void levelOne();
void levelTwo();
void levelThree();
void levelCustom(int difficulty);
#endif // LEVELS_H_INCLUDED
Inside my levels.c file:
void levelOne()
{
//level scope of 1 to 10
srand(time(NULL));
int randomNum = (rand() % 9)+1);
printf("the random number is: %i\n", randomNum);
}
levels.c is not getting passed into the compiler, are you sure you have included levels.c in the whole project? If not it will not link. You need a project if you want to compile multiple files. In CodeBlocks, the sources and the settings for the build process are stored in a project file <name>.cbp
Here is the User Manual
gcc levels.c main.c should link successfully. gcc main.c will only compile one file and try and link to create final executable and levelOne() will not be found. since it is in file levels.c
You need to include levels.h in levels.c as well or if a function (physically) above levelOne calls it, it is undefined.
Then compile it with gcc -Wall *.c -o myapp to compile and link all of the c files in that directory into myapp (or you can name them individually) with (almost) all warnings enabled. This is provided you have it in its own directory.
Once you get into larger projects with more code, you can compile individual .c files into .o object files with gcc -Wall -c somecode.c and then link all the objects with gcc *.o -o myapp. If it gets really large, you'll want a build system to help with rebuilding objects only when its code (or dependent code) changes (such as Makefiles, waf, and dare I say autotools).
I had this exact same problem, the solution is easy. Right click on levels.c and select properties. A properties window should come up select the "Build" tab tick compile file, link file, and in the box check debug and release. This should fix your problem.
Don't make the mistake of doing this with a header file because it will give you a "...h.gch: file not recognized: File format not recognized.." error.

Call method from source file in another directory

I have a newbie question about the C programming language. I have looked around to find the answer in similar questions but I failed to figure it out.
Assume a simple project consisting of two dirs: src and test. The source and header files are defined by src/main.c, test/foo.h and test/foo.c.
src/main.c:
#include "../test/foo.h"
int main (void) {
int a = VAR; /* works, recognizes declared macro */
some_function(a); /* doesn't work, "undefined reference" */
}
test/foo.h:
#ifndef FOO_H
#define FOO_H
void some_function(int a);
#define VAR 2;
#endif
test/foo.c (redundant but to be complete):
#include "foo.h"
#include <stdlib.h>
void some_function(int a) {
printf("%d", ++a);
}
I created the project in Eclipse and I also compile with it, I figured it wasn't a linking error since the macro gets recognized but the method is not callable.
The reason why I'm using different directories is because I have a lot of files and would like my test code to be separate from my main source code. Note that src and test have the same parent directory.
Any ideas what's going on here? Am I missing something very obvious?
Any help would be much appreciated, thanks in advance!
edit: I'm working on a (Debian) Linux machine and Eclipse uses the gcc compiler.
edit2: Thanks to H2CO3's answer I learned it is indeed a linking error. Since compiling and linking manually every time is quite an overhead, I was wondering if anyone knows how to teach Eclipse to link executables from different directories?
--------------------- SOLUTION ---------------------
edit3: Lol the solution was very easy after all, all I had to do was create a "new source folder" rather than a "new folder". I feel stupid but thanks to you all for replying, H2CO3 in particular!
I figured it wasn't a linking error since the macro gets recognized but the method is not callable.
Non sequitur. Macros are expanded in the preprocessing phase. (And as such, they have nothing to do with linkage at all.) You do have a linker error.
What you have to do is compile both files then link them together, so something like this should work:
gcc -Wall -o dir_one/foo.o dir_one/foo.c
gcc -Wall -o dir_two/bar.o dir_two/bar.c
gcc -o my_program dir_one/foo.o dir_two/bar.o
Also, read this SO question/answer and/or this article to understand how the steps of the compilation process work together. (These are almost the same for C and C++, it's only the name mangling that usually differs.)

Resources