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.)
Related
I am having some issues with putting multiple .c files together.
I will mimic my situation with the following files.
mod.c
#include <stdio.h>
void print_hello() {
printf("Hello!");
}
mod_main.c
#include "mod.c"
int main() {
print_hello();
}
Compiling scenarios:
#1
$ cc -o mod_main mod_main.c
# No errors
#2
$ cc -c -o mod_main.o mod_main.c
$ cc -c -o mod.o mod.c
$ cc -o mod_main mod.o mod_main.o
duplicate symbol '_print_hello' in:
mod.o
mod_main.o
ld: 1 duplicate symbol for architecture x86_64
#3
$ cc -o mod_main mod.c mod_main.c
duplicate symbol '_print_hello' in:
Based on these attempts, I gather that, I can compile simply mod_main.c & get it working. Or, I can create a .h file as follows & get it working.
mod.h
void print_hello(void);
mod.c
#include <stdio.h>
#include "mod.h"
void print_hello() {
printf("Hello!");
}
mod_main.c
#include "mod.h"
int main() {
print_hello();
}
I like to know, if there are any other ways to compile multiple C files that has dependencies within each other. To be precise, is there a decent way to avoid writing header files?
Good day!
PS: I have explored similar questions on StackOverflow. None of them that I could find where asking the exact questions as mine.
First of all, including source files is generally a bad idea.
As for the problem itself, you can easily solve it by pretending you're writing a header file, but instead write all declarations, structure definitions and macros in a source file. Then copy-paste it into the other source files who needs it.
But, and this is a very important but, this is extremely error-prone. If the signature (e.g. argument list) of a function changes, or a structure is modified, or a macro gets a different value, then you must remember to modify this everywhere. If you have more than a couple of source files it becomes easy to miss one of the files.
If a function with the wrong signature is called, or you have structures that are not character-by-character copies of each other, then that will lead to undefined behavior. Mismatching macros might not be so serious, but if it's an array-limit that is changed (for example) then it's easy to go out of bounds where you miss to update the macro.
In short: It's possible, but not a good idea. Use one or more header files for common declarations, structures and macros.
I've added a new function wiringPiVersion() to wiringPi, but after I build and install the shared library, when I attempt to compile a small C program around it, I get:
wpi_ver.c:(.text+0xc): undefined reference to `wiringPiVersion'
However, when I include it in an XS based Perl module, all works well. I don't know enough about C to figure out what's going wrong here, and I've been searching for the better part of two hours trying different things to no avail.
Here's my small C program to test the new function:
#include <stdio.h>
#include <wiringPi.h>
int main (){
char * ver = wiringPiVersion();
printf("wiringPi version: %s\n", ver);
return 0;
}
Compilation that throws the error:
gcc -o ver wpi_ver.c -lwiringPi
The addition to wiringPi's header file:
extern char * wiringPiVersion(void);
The wiringPi's .c file addition:
#define WPI_VERSION "2.36"
char * wiringPiVersion(void){
return WPI_VERSION;
}
In my Perl module's XS file, I have:
char *
wiringPiVersion()
...and my Perl module's Makefile.PL
LIBS => ['-lwiringPi'],
...and after re-installing the Perl module, I can access the function without any issues in a test script.
I'm hoping this is something simple I'm overlooking which someone may be able to point out. My question is, how do I rectify this?
So it turned out that there were two .so files generated when I rebuilt wiringPi... one in the wiringPi's build directory way under my home directory, and the other in /usr/local/lib.
After a tip in comments, I added the library path explicitly:
gcc -o ver wpi_ver.c -L/usr/local/lib -lwiringPi
...and it all fell together and works as expected:
$ ./ver
wiringPi version: 2.36
Note: I have sent Gordon the patch in hopes it gets included in the next wiringPi cut.
Update: I received an email back from Gordon and he stated that currently, only the gpio application has the ability to report the version, so he advised that he's going to add something similar to my patch in a future release.
Although already solved, I added this answer to show what gave me the hint.
Error message "undefined reference" points to a linker error (cf. answer on SO), so its about checking if the correct library is drawn.
Ever since Go 1.5 came out, I started taking another look at how I could integrate it into an existing project of mine.
The project's codebase is written entirely in C for low level access to to hardware and other fun stuff. However, some of the higher level things are tedious, and I would like to start writing them in a higher level language (Go)
Is there any way I can call Go code from a C program? I installed Go 1.5, which added -buildmode=c-archive (https://golang.org/s/execmodes) which I am trying to get working.
However, I can't seem to get Go to generate the appropriate header files to allow my project to actually compile. When I generate the archive, I see the function in the exported symbols (using objdump), but without the header files to include gcc complains about the function not existing (as expected)
I'm quite new to Go - however, I love the language and would like to make use of it. Is there any idiomatic way ("idiomatic" gets used a lot in the world of Go I see...) to get this to play nicely with each other?
The reason I asked this question and specifically mentioned Go 1.5 is that according to this document, https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.1gw5ytjfcoke
Go 1.5 added support for non-Go programs to call Go code. Specifically, mentioned under the section "Go code linked into, and called from, a non-Go program"
To build an archive callable from C, you will need to mark them as exported CGo symbols.
For example, if I create a file foo.go with the following contents:
package main
import (
"C"
"fmt"
)
//export PrintInt
func PrintInt(x int) {
fmt.Println(x)
}
func main() {}
The important things to note are:
The package needs to be called main
You need to have a main function, although it can be empty.
You need to import the package C
You need special //export comments to mark the functions you want callable from C.
I can compile it as a C callable static library with the following command:
go build -buildmode=c-archive foo.go
The results will be an archive foo.a and a header foo.h. In the header, we get the following (eliding irrelevant parts):
...
typedef long long GoInt64;
...
typedef GoInt64 GoInt;
...
extern void PrintInt(GoInt p0);
...
So that's enough to call the exported function. We can write a simple C program that calls it like so:
#include "foo.h"
int main(int argc, char **argv) {
PrintInt(42);
return 0;
}
We can compile it with a command like:
gcc -pthread foo.c foo.a -o foo
The -pthread option is needed because the Go runtime makes use of threads. When I run the resulting executable it prints 42.
The code above work just fine, but gcc will complain about functions and headers.
The includes should be:
#define _GNU_SOURCE
#include <stdio.h>
#include "mygopkg.h"
If you forget the #define _GNU_SOURCE, the gcc will complain:
warning: implicit declaration of function 'asprintf'; did you mean 'vsprintf'? [-Wimplicit-function-declaration]
If you forget the #include "mygopkg.h", the gcc will complain:
warning: implicit declaration of function 'PrintString' [-Wimplicit-function-declaration]
The last but not less important. The build command line I recommend for production code is:
go build -ldflags "-s -w" -buildmode c-archive -o mygopkg.a
It'll save you 53% size of final mygopkg.a.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
So I have 2 files I need to turn in, call them: example.cc and example.h
We've been told that their test code will only #include "example.h"
Normally I've always used #include "example.cc" as this will have already included example.h in it's declaration.
When I run the test code, I simply get "Undefined reference to example::example.." anytime I mention example in the test code, this is obviously because the test code can only see my delcarations in example.h, not their actual implementation.
What am I missing? I've tried #including example.cc in example.h, but this obviously isn't right.
It seems likely that your professor has some sort of other file, say professor_main.cc, and that they will compile the project like this:
g++ example.cc professor_main.cc -o project
Their professor_main.cc will have a line
#include "example.h"
and it will also use a few of your functions, and likely test that they're doing the right thing:
std::cout << (example_add(2,3) == 5) ? "good" : "bad" << std::endl;
Now, if they didn't #include example.h, or if you didn't make that file correctly, they would get a compile error on professor_main.cc, because it wouldn't know about example_add(int,int). The crucial line that should be in the header file and that makes this error go away is:
int example_add(int a, int b);
This is called a function declaration.
If everything's done correctly with the header, but your professor made a mistake and tried to compile the project without example.cc, like this:
g++ professor_main.cc -o project
Then they would get a linker error about an "undefined reference" to example_add().
What's missing is the function definition:
int example_add(int a, int b) { return a + b; }
This should be in your example.cc file, and if the professor includes that on their compilation command line, all should be well.
However, if you did #include "example.cc" in your header file, all would not be well. Effectively, you would then have copied-and-pasted example.cc into professor_main.cc, because it's #included there. But it's also obviously still in its own file, example.cc. So if your professor tried to do this:
g++ example.cc professor_main.cc -o project
They would get a multiple definition error from the linker, because the function example_add() would've been defined twice.
Generally, then, what you're probably supposed to do is put all your function definitions in your source file (.cc) and all your function declarations in your header file (.h). Try compiling with another .cc file yourself and experiment to see how it works.
In C++ (and C, from which it descends) the idea is that header files (*.h in C, no extension in C++) contain declarations (no executable code, except for inline functions), while code files (*.c in C,*.ccin C++) contain all executable code, and#include` the headers that declare what they need. Note that the file implementing some funky class for wider use should also include the header where it is declared, to avoid hard to track down bugs due to differing declarations.
The C/C++ preprocessor is a dumb beast, it just replaces text, and #include just copies the contents of the file verbatim. So you can do all sorts of weird contortions, like starting a statement in the #incuded file ind finish it outside, or include executable code in the header. I will compile and work fine, but what really matters is if the next human reading the code understands it (and by that I mean you in a couple of days). Your TA won't suffer from your badly organized code, she will just wrinkle her nose and give you an F. You will, while trying to get it to work.
What they presumably mean is that you should implement, say class foo, give the needed declarations to use class foo in header file foo.h (and only what the unwashed masses should see of how class foo works!), and a code file foo.cc giving the actual implementation; they will supply bar-uses-foo.cc which includes foo.h and links against foo.o to test your class.
You need to use your compiler to link the file and then build them. Another thing is than in each of the files except the header file, you need to include the header.
something like this should help
gcc -c example.c -o example.o
gcc example.o -o example
if you add another file that uses the header:
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc file1.o file2.o -o myprogram
The terms gcc and g++ are both Linux and Unix compilers.
if you are using windows dev c++ should work or use gcc for windows
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.)