How do you have a header file for a function and the implementation of that function in different files? Also, how do you have main in yet another file and call this function?
The advantage is so that this function will then be an independent component which can be reused, right?
This is best illustrated by an example.
Say we want a function to find the cube of an integer.
You would have the definition (implementation) in, say, cube.c
int cube( int x ) {
return x * x * x;
}
Then we'll put the function declaration in another file. By convention, this is done in a header file, cube.h in this case.
int cube( int x );
We can now call the function from somewhere else, driver.c for instance, by using the #include directive (which is part of the C preprocessor) .
#include "cube.h"
int main() {
int c = cube( 10 );
...
}
Finally, you'll need to compile each of your source files into an object file, and then link those to obtain an executable.
Using gcc, for instance
$ gcc -c cube.c #this produces a file named 'cube.o'
$ gcc -c driver.c #idem for 'driver.o'
$ gcc -o driver driver.c cube.c #produces your executable, 'driver'
Actually you can implement any function in header files for better performance(when implementing libraries for example) as long are not referenced to a specific object(actually it won't compile that).
By the way even with that way, you have separate interface and implementation ;)
Of course you will have include gurads in you header files to avoid "multiple definition" errors.
In C/C++, non-inline functions should be defined only once. If you put function defination
in header files, you will get "multiple defination" link error when the header file is included more than once.
Related
So I have this C program:
#include <stdio.h>
int helloworld()
{
return 12;
}
And I compile this using:
gcc -shared -o libhello.so main.c
This gives me a libhello.so file.
Now, I am loading this function in another project using dlopen.
My question is, is there any way for me to "list" functions in the libhello.so file, along with their return types and arguments?
I am working with a system where users create plugins using .so files, so exactly how the functions are defined is unknown to me.
Basically, I want to dynamically create function pointers for functions defined in the .so file.
Thank you!
you may be able to parse through a .so file and manage to get function names (assuming that they're not obfuscated). But it is not possible to get the data types of arguments and return type. This is the reason that so files comes with corresponding header files.
Let's suppose that I write some functions in a file, that we'll call foo.c.
This is foo.c:
int d;
typedef int bar;
int foo(int a, int b){
...
}
void boo(){
...
}
char *test(){
...
}
Now, boo is a function used only inside foo.c, while foo(), test(), d, and Bool will need to be able to get called inside other files.
In order to do that, I know that I have to create a foo.h file and write it like this:
extern int d;
extern typedef int bar;
int foo(int a, int b);
char *test();
then #include "foo.h" in the foo.c file, and whenever I want to use the types and functions defined in foo.c, I have to include both foo.hand foo.cin the file in which I wanna use foo.c functions and types.
So foo.c in the end would look like this:
#include "foo.h"
int d;
typedef int bar;
int foo(int a, int b){
...
}
void boo(){
...
}
char *test(){
...
}
Here are my questions.
Q1. Is this how you actually do it? Since foo.h is already included in foo.c, wouldn't it be sufficient to include only foo.c in the file in which I want to use its functions? Can't I just directly define the functions inside of the foo.c file, not using the foo.h file at all?
Q2. Do you actually have to put the extern in front of typedefs in the foo.h file?
Q3. Let's say that in foo.c I use some standard C libraries like string.h and math.h . Where should I include them? Directly in the foo.c file, in the foo.h file or in both? Are #ifndef instructions necessary? If so, how do you use them correctly?
Q4. After writing the foo.c and foo.h file, am I all ready to go? Like, I don't need to compile them or anything, right? I can just #include them wherever I need just like that?
Q5. Somewhere else I've read that if I want to use a custom library these are the steps that I need to follow:
define the interface (foo.h)
write foo.c #include ing foo.h
creating an object file like this gcc -o foo.o -c foo.c
including foo.h in the program in which I want to use foo.c functions
linking the object file like this gcc my_proj.c foo.o
Are these steps actually necessary? Because I haven't seen them mentioned anywhere else. Why do I only need to include foo.h in the file in which I want to use foo.c functions? What exactly is an object file?
Thanks for your time and sorry if this is a bit lengthy
Q1. Is this how you actually do it? Since foo.h is already included in foo.c, wouldn't it be sufficient to include only foo.c in the file in which I want to use its functions?
You just don't include .c files. In your case, foo.c and the other files are separate compilation units which get linked together in the end.
Q2. Do you actually have to put the external in front of typedefs in the foo.h file?
No, typedefs don't need extern.
Q3. Let's say that in foo.c I use some standard C libraries like string.h and math.h . Where should I include them? Directly in the foo.c file, in the foo.h file or in both? Are #ifndef instructions necessary? If so, how do you use them correctly?
If you need these files in the .h as well, you include them there (e. g. for types used in function prototypes). If you need them only in your .c, include them there.
Q4. After writing the foo.c and foo.h file, am I all ready to go? Like, I don't need to compile them or anything, right? I can just #include them wherever I need just like that?
You can compile them in order to get something callable. If you don't compile your program, you cannot use it. Or do I understand you wrong?
Q5. Somewhere else I've read that if I want to use a custom library these are the steps that I need to follow:
[snip]
Indeed, this is one way to go. The steps 1, 2 and 4 cannot be omitted for obvious reasons. But you can execute step 3 and 5 together by doing
gcc my_proj.c foo.c
This compiles the given files and then links them together in one call.
Why do I only need to include foo.h in the file in which I want to use foo.c functions?
That's because the resulting object file contains information for the linker about which function it needs from other object files.
What exactly is an object file?
It is what results from compiling one source file. If you link several object files together, you get a running executable.
In other words: An object file is the compiled version of a source file. It "provides" the identifiers needed by other object files, and it "requires" other identifiers provided by other files. Linking them together means that the required and the provided objects are connected in an appropriate way so that the program can run.
Example: You have a foo.c which defines the functions foo and test. Then you have a main.c which makes use of these functions and provides a function main. In the end, they are linked together and combined with the startup code which is needed to start a program and which calls main(). The points in main() where foo() and test() are called respectively are marked in a special way so that the linker can put the actual call address there.
Q1. Is this how you actually do it?
No
Since foo.h is already included in foo.c, wouldn't it be sufficient to
include only foo.c in the file in which I want to use its functions?
You should only include .h files; both in the file that defines them, and in the ones that use them. As an extra, that include should be the first one in the file that defines the functions, but in the files that use them, it should go after the rest (standard headers, other packages' headers, ...); the reason for this is to detect errors easily.
Can't I just directly define the functions inside of the foo.c file,
not using the foo.h file at all?
Usually, no. Only static inline functions should do that.
Q2. Do you actually have to put the extern in front of typedefs in
the foo.h file?
No: typedef int foobar_t;
Q3. Let's say that in foo.c I use some standard C libraries like
string.h and math.h . Where should I include them?
In the file that needs them (foo.c). Include in every file only the headers that it needs. No more; no less.
Directly in the foo.c file, in the foo.h file or in both?
foo.c
Are #ifndefinstructions necessary? If so, how do you use them
correctly?
Yes:
// foo.h
#ifndef FOO_H
#define FOO_H
Here go all the contents of foo.h
#endif /* foo.h */
Q4. After writing the foo.c and foo.h file, am I all ready to go?
Like, I don't need to compile them or anything, right? I can
just #include them wherever I need just like that?
You need to compile foo.c into foo.o (object file) and then you probably would like to do a static library (.a) or a dynamic one. You can include it wherever you want, but you will need to prepare your Makefile to do so.
Q5. Somewhere else I've read that if I want to use a custom library
these are the steps that I need to follow:
define the interface (foo.h)
write foo.c #include ing foo.h
creating an object file like this gcc -o foo.o -c foo.c
including foo.h in the program in which I want to use foo.c functions
linking the object file like this gcc my_proj.c foo.o
Are these steps actually necessary?
Yes
Because I haven't seen them mentioned anywhere else. Why do I only
need to include foo.h in the file in which I want to
use foo.c functions?
Read more about compiling and linking.
What exactly is an object file?
A compiled file. Many of them are usually linked together to produce the executable file.
I write C library and I don't know how make some functions invisible for user (which are used to implement functionality). There is any way in C? And my second question is: when I include some library in .h or .c file (let's see math.h) is there any problem when user declare the same header in his program (which use my library of course)?
And how about structure? Is there any key word?
how to make some functions invisible ?
do not declare the function in the header file of your library
define the function as static in the source file of your library
Example:
your-lib.h
#ifndef YOUR_LIB_H
#define YOUR_LIB_H
void do_public_stuff(void);
#endif YOUR_LIB_H
your-lib.c
#include "your-lib.h"
// this functions is invisible
static void do_private_stuff(void)
{
// ...
}
// this functions is visible
void do_public_stuff(void)
{
// ...
}
user-code.c
#include "your-lib.h"
int main(void)
{
do_public_stuff();
return 0;
}
A usual way is to make implementation functions static that is to declare them with storage specifier static and place them in modules with code. So neither header will have references to these functions.
You can use the keyword static as the other answers suggested.
But sometimes, the library itself will consist of several source- and object-files, and there might be functions, which have to be used throughout the whole library, but shall not be exported after linking.
Simple example:
Your library has 3 objects: lib1.o lib2.o util.o
Located in util.o are several helper-functions, which are used by lib1.o and lib2.o. You cannot use static here, because the functions would not be visible to them and linking would fail.
What you can do:
Make the helper-functions non-static and provide the linker with a version script, which only exports the needed symbols:
gcc -shared lib1.o lib2.o util.o -o mylib.so -Wl,--version-script=map
The file map could have the following content:
{
global:
bar;
baz;
local: *;
};
This would only export the symbols bar and baz (which are the relevant API-functions for this sample lib), while omitting all other symbols from the symbol table.
I would like to know , if I have source file like this
#include <stdio.h>
int main()
{
printf("Hello world");
}
as I know header files contains only prototypes of functions. If it so how can my source file get the function printf ? If I don't include the source file where it has been declared?
thank you
The question is not clear, but there are 2 things which happen before a program gets created,
Compiling (requires prototypes / declarations)
Linking (requires definitions).
Header information is needed for knowing prototypes. Even this would compile fine:
int printf ( const char * format, ... );
int main()
{
printf("Hello world");
}
On linking there will be no issues because the printf function is found in the C standard library, so on linking it will look into the standard directories (of the compiler where the library is kept - bin/lib folder) and link the function.
The source only needs to know the prototype. The problem a programmer will have in this case:
int my_printf ( const char * format, ... );
int main()
{
my_printf("Hello world");
}
The above will compile, but when linking my_printf your code will not have a definition so it will give an error on linking.
Header file has the definitions declarations of the functions ( stdio.h has definition declaration for printf ). The actual function exists in the libraries and gets linked when you compile the code.
When it comes to using libraries, you include the header of the library in your code and you instruct the linker to link using the code files of that library(usually object files). For the standard libraries, the IDE usually instructs the linker to link to them by default.
Assuming you're using gcc as a compiler the standard libraries are linked by default and that is where the function definitions lie. If you'd like to see exactly which libraries are being linked you can pass gcc the -v option which will cause it to dump information about the default options it will use including the library paths and default libraries and object files that will be linked in.
If you give the -Wl,--verbose option, gcc will pass the --verbose to the linker which will dump exactly where it's looking for libraries, including both failed and successful searches
gcc -v foo.c -Wl,--verbose
The header file stdio.h would declare printf as an extern function, i.e., it is defined elsewhere. The compiler is happy as long as functions you use have a declaration. The linker is the one that resolves these dependencies.
A very useful thing to do when you start asking good questions like this is to play with some linker commands.
Assuming you're on *nix, once you have your executable file (lets call it foo), do:
ldd foo
You should see a list of libraries that were linked with while creating foo.
libc.so should be one among those. It contains the definition for printf among other things!
You can refer to this link to learn more
This has gotten a bit lost in translation so I am going to be more precise:
we have classes recursion.c, fib.c, and countUp.c. from recursion.c we have to recursively call fib.c or countUp.c, decided by the input argument. I can't use header files and am only given that I must place prototypes:
int fib(int n);
and
void countUp(int n);
My Makefile
TAR = tar
COMPILER_FLAGS = -g -Wall -std=c99 -c
LINKER_FLAGS = -g -o
OBJS = recurse.o
C_FILES = recurse.c fib.c countUp.c
ASM_FILES = recurse.asm
TARGET_FILE = recurse
TARGET_TAR = PA5.tar
$(TARGET_TAR): $(TARGET_FILE)
$(TAR) -cvf $(TARGET_TAR) $(C_FILES) $(ASM_FILES) $(TARGET_FILE) Makefi$
recurse.o: recurse.c
$(C_COMPILER) $(COMPILER_FLAGS) $(C_FILES)
$(TARGET_FILE): $(OBJS)
$(LD_LINKER) $(LINKER_FLAGS) $(TARGET_FILE) $(OBJS)
where fib and countUp class methods must be called recursively. The recursive.c file is considered our c driver. Do not create or implement any header files OTHER than those that are standard c headers (stdio.h, string.h, etc.). When I try to run this I get:
make
gcc -g -o recurse recurse.o
recurse.o: In function `main':
(file root location)/recurse.c:43: undefined reference to `fib'
(file root location)/recurse.c:46: undefined reference to `countUp'
collect2: ld returned 1 exit status
make: *** [recurse] Error 1
Any clue what is going on.
Original Question:
I have multiple C files that I am combining into an executable. For example say I have math.c, the arguments are passed into it, and then if the input argument calls add it performs functions from add.c, if the argument calls subtract it will call functions from subtract.c, etc. The files are then compiled into a .o file, and then an executable is created. The issue I have is not being able to utilize header (.h) files. Is there any way to break into the separate classes or am I missing something? I really don't know exactly how to ask the question, jargon is pretty bad as far as C goes, sorry :(
I don't really get the idea of a driver I guess. (Not a device driver, she keeps telling us this is a c executable driver).
If I understood correctly, what I think you need to do is add the following prototypes above any of the functions you define in recursion.c. The prototypes will allow you to call these functions from within any function inside recursion.c (In fact, including a header file is akin to copy-pasting all of the prototypes defined in the file, as #Justin and #EdS already pointed out)
int fib(int n);
void countUp(int n);
int main() {
...
}
Then you need to make sure that your project file includes the files recursion.c, fib.c, and countUp.c - When you build your project, the linker will do its job and lookup the entry points in your compiled object files, and will proceed to assemble a single executable file.
What compiler are you using?
Including a header file is just a preprocessor directive to include the contents of that file at the location of the include. To achieve the same thing without a header file just copy and paste the code that you would have put in the header file into the top of each c file.
Of course this isn't very maintainable as if you want to change that contents you need to change it in many files, hence why header files exist in the first place.
Since this is homework and considering the fact that you have told us that A) You have no header files to use, and B) you have not been instructed to utilize the extern keyword, it seems to me that your only choice is to include the .c files themselves:
#include "add.c"
#include "subtract.c"
/* etc... */
int main()
{
// use functions defined in "add.c", "subtract.c", etc.
}
Note that this is bad form as you are including the implementation instead of the interface and likely pulling in a bunch of stuff you don't want or need. If that doesn't answer your question then there is something, some instruction from your teacher, missing in the question.