So I made a program that uses four differrent processes to do some stuff. I works perfectly, but now I want to split it up so each of the processes has its own .c file. I tried to do this using a header file "processes.h" that has the function prototypes for all the processes. It looks like this:
#ifndef PROCESSES_H_
#define PROCESSES_H_
/*------------------------------------------------------------------------------
definitions (defines, typedefs, ...)
------------------------------------------------------------------------------*/
#define NR_OF_PROCESSES 4
enum errCode {
ERR_NONE = 0, ERR_SYNTAX, ERR_OPEN, ERR_TOKEN, ERR_ARG, ERR_END
};
typedef enum errCode ErrCode;
enum toktype {
NUMBER = 0, OPERATOR, ENDOFLINE, ENDOFFILE
};
typedef enum toktype Token;
/*------------------------------------------------------------------------------
function prototypes
------------------------------------------------------------------------------*/
void readProcess(int pfds[5][2]);
void tokenProcess(int pfds[5][2]);
void calculatorProcess(int pfds[5][2]);
void errorProcess(int pfds[5][2]);
/*------------------------------------------------------------------------------
global variable declarations
------------------------------------------------------------------------------*/
void (*functionTable[NR_OF_PROCESSES]) (int pfds[5][2]) = {
readProcess,
tokenProcess,
calculatorProcess,
errorProcess
};
#endif /*PROCESSES_H_*/
All the .c files which contain the implementation of the function #include "processes.h", and the main function (which uses the functionTable to set up the processes) also includes processes.h.
When I try to compile I get the error:
ld: duplicate symbol _functionTable in /var/folders/eH/eHF8LmdvHzSsNgT01V3jyk+++TI/-Tmp-//ccDgTW2X.o and /var/folders/eH/eHF8LmdvHzSsNgT01V3jyk+++TI/-Tmp-//ccp7zO9L.o
collect2: ld returned 1 exit status
Is this the right way of doing the splitting up into different files? Or do I need a separate .h file for each .c file?
Put this in your .h:
extern void *functionTable;
Then put this in exactly one file, e.g. the source file with "main()":
#include "processes.h"
...
void (*functionTable[NR_OF_PROCESSES]) (int pfds[5][2]) = {
readProcess,
tokenProcess,
calculatorProcess,
errorProcess
};
One way to do this is to put
#ifdef GENERATE_DEFINITIONS
#define EXTERN
#define INITIALIZE(x) = x
#else
#define EXTERN extern
#define INITIALIZE(x)
#endif
EXTERN void (*functionTable[NR_OF_PROCESSES]) (int pfds[5][2])
INITIALIZE({
readProcess,
tokenProcess,
calculatorProcess,
errorProcess
});
in processes.h and then put
#define GENERATE_DEFINITIONS
before the
#include "processes.h"
in just one of the source files (e.g., the one containing main()).
Related
Can anyone explain how to create a header file in C with a simple example from beginning to end.
foo.h
#ifndef FOO_H_ /* Include guard */
#define FOO_H_
int foo(int x); /* An example function declaration */
#endif // FOO_H_
foo.c
#include "foo.h" /* Include the header (not strictly necessary here) */
int foo(int x) /* Function definition */
{
return x + 5;
}
main.c
#include <stdio.h>
#include "foo.h" /* Include the header here, to obtain the function declaration */
int main(void)
{
int y = foo(3); /* Use the function here */
printf("%d\n", y);
return 0;
}
To compile using GCC
gcc -o my_app main.c foo.c
#ifndef MY_HEADER_H
# define MY_HEADER_H
//put your function headers here
#endif
MY_HEADER_H serves as a double-inclusion guard.
For the function declaration, you only need to define the signature, that is, without parameter names, like this:
int foo(char*);
If you really want to, you can also include the parameter's identifier, but it's not necessary because the identifier would only be used in a function's body (implementation), which in case of a header (parameter signature), it's missing.
This declares the function foo which accepts a char* and returns an int.
In your source file, you would have:
#include "my_header.h"
int foo(char* name) {
//do stuff
return 0;
}
myfile.h
#ifndef _myfile_h
#define _myfile_h
void function();
#endif
myfile.c
#include "myfile.h"
void function() {
}
header files contain prototypes for functions you define in a .c or .cpp/.cxx file (depending if you're using c or c++). You want to place #ifndef/#defines around your .h code so that if you include the same .h twice in different parts of your programs, the prototypes are only included once.
client.h
#ifndef CLIENT_H
#define CLIENT_H
short socketConnect(char *host,unsigned short port,char *sendbuf,char *recievebuf, long rbufsize);
#endif /** CLIENT_H */
Then you'd implement the .h in a .c file like so:
client.c
#include "client.h"
short socketConnect(char *host,unsigned short port,char *sendbuf,char *recievebuf, long rbufsize) {
short ret = -1;
//some implementation here
return ret;
}
I have defined an enum in a header file,
global.h:
Typedef enum
{
ELEMENT1,
ELEMENT2,
ELEMENT3
}e_element;
I have a second file using the enum as a function parameter.
file2.c
#include global.h
#include file2.h
Function(e_element x)
{
Body…
}
The prototype is in:
file2.h
Function(e_element x);
The compiler doesn’t know e_element in file2.h. I have tried putting the #include for global.h in both file2.c and file2.h, but it still doesn’t see it. I would put the enum in file2.h, except that it is used by several other files, so if I move it the problem will just show up somewhere else.
How can I get the file2.h prototype to see e_element?
This worked for me:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
typedef enum
{
ELEMENT1,
ELEMENT2,
ELEMENT3
}e_element;
#endif
file2.h
#ifndef FILE_2_H
#define FILE_2_H
#include "global.h"
int test(e_element);
#endif
file2.c
#include "file2.h"
int test(e_element x)
{
return x == ELEMENT1;
}
int main() {
return 0;
}
edit:
#ifndef is conventionally used as a "header guard". It prevents a header file from being included multiple times by the preprocessor, which prevents things from being defined multiple times. It works by checking if a unique symbol has been defined before. If it has not, then it immediately defines it and then continues with the header file until #endif. If the symbol was already defined then it skips the guarded code completely, preventing multiple definitions. An example of multiple definitions would be if the same header file was included in a source and a header that the source also includes.
See this link for more information.
I want to declare and define (with a default value) a variable in a .h file.
When I do that I get
/tmp/cc19EVVe.o:(.data+0x0): multiple definition of `car_name'
/tmp/cc3twlar.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
How do I achieve my goal? Namely, to declare and define with default values a variable in a .h file and use that variable in multiple .c files?
Here is the A.h file
char * car_name = "Volkswagen";
void execute();
Here are the first file that uses the variable car_name defined in A.h: (The file is called execute.c)
#include "A.h"
#include <stdio.h>
#include <string.h>
void execute(){
int len = sizeof(car_name) + 2;
char car_name_with_new_line[len];
strncat(car_name_with_new_line, car_name, sizeof(car_name));
strncat(car_name_with_new_line, "\n", 1);
printf(car_name_with_new_line);
}
That's the other .c file: (It's called main.c)
#include "A.h"
int main(int argc, char ** argv){
execute();
return 0;
}
The answer is simple: Define your variables in exactly one compilation unit (.c file). Declare them in the header file associated with that .c file.
foo.h
extern char *g_name; // Declare that g_name exists
foo.c
#include "foo.h"
char *g_name; // Define g_name in one place
static char *m_private; // Private to foo.c, not "exported" via foo.h
main.c
#include "foo.h"
void somefunc(void)
{
// use g_name
}
1) define the variable in a single file, do not add a static modifier
2) place an extern statement for that variable in the header file.
then only one instance of the variable exists anyone that includes the header file can access the variable.
Note: it is poor programming practice to have global variables.
Good programming practice is to write accessor functions and hide the variable within a file. similar to the following:
static int myVariable = 0;
void setMyVariable( int myVariableParm )
{
myVariable = myVariableParm;
}
int getMyVariable( void )
{
return myVariable;
}
How can I create global variables that are shared in C? If I put it in a header file, then the linker complains that the variables are already defined. Is the only way to declare the variable in one of my C files and to manually put in externs at the top of all the other C files that want to use it? That sounds not ideal.
In one header file (shared.h):
extern int this_is_global;
In every file that you want to use this global symbol, include header containing the extern declaration:
#include "shared.h"
To avoid multiple linker definitions, just one declaration of your global symbol must be present across your compilation units (e.g: shared.cpp) :
/* shared.cpp */
#include "shared.h"
int this_is_global;
In the header file write it with extern.
And at the global scope of one of the c files declare it without extern.
In the header file
header file
#ifndef SHAREFILE_INCLUDED
#define SHAREFILE_INCLUDED
#ifdef MAIN_FILE
int global;
#else
extern int global;
#endif
#endif
In the file with the file you want the global to live:
#define MAIN_FILE
#include "share.h"
In the other files that need the extern version:
#include "share.h"
You put the declaration in a header file, e.g.
extern int my_global;
In one of your .c files you define it at global scope.
int my_global;
Every .c file that wants access to my_global includes the header file with the extern in.
If you're sharing code between C and C++, remember to add the following to the shared.hfile:
#ifdef __cplusplus
extern "C" {
#endif
extern int my_global;
/* other extern declarations ... */
#ifdef __cplusplus
}
#endif
There is a cleaner way with just one header file so it is simpler to maintain.
In the header with the global variables prefix each declaration with a keyword (I use common) then in just one source file include it like this
#define common
#include "globals.h"
#undef common
and any other source files like this
#define common extern
#include "globals.h"
#undef common
Just make sure you don't initialise any of the variables in the globals.h file or the linker will still complain as an initialised variable is not treated as external even with the extern keyword. The global.h file looks similar to this
#pragma once
common int globala;
common int globalb;
etc.
seems to work for any type of declaration. Don't use the common keyword on #define of course.
There is a more elegant way to create global variables.
Just declare the variables as static inside a ".c" source file and create set/get functions.
The example below I use to override malloc, realloc and free functions during memory allocation tests.
Example:
memory-allocator.h
#ifndef MEMORY_ALLOCATOR_H_
#define MEMORY_ALLOCATOR_H_
#include <stddef.h>
void std_set_memory_allocators(void *(*malloc)(size_t size),
void *(realloc)(void *ptr, size_t size),
void (*free)(void *ptr));
void std_set_reset_allocators();
void *std_malloc(size_t size);
void *std_realloc(void *ptr, size_t size);
void std_free(void *ptr);
#endif // MEMORY_ALLOCATOR_H_
memory-allocator.c
#include "memory-allocator.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
void *(*malloc)(size_t size);
void *(*realloc)(void *ptr, size_t size);
void (*free)(void *ptr);
} StdMemoryAllocator;
StdMemoryAllocator memory_allocators = {&malloc, &realloc, &free};
void std_set_memory_allocators(void *(*malloc)(size_t size),
void *(realloc)(void *ptr, size_t size),
void (*free)(void *ptr)) {
memory_allocators.malloc = malloc;
memory_allocators.realloc = realloc;
memory_allocators.free = free;
}
void std_set_reset_allocators() {
memory_allocators.malloc = malloc;
memory_allocators.realloc = realloc;
memory_allocators.free = free;
}
void *std_malloc(size_t size) {
return memory_allocators.malloc(size);
}
void *std_realloc(void *ptr, size_t size) {
return memory_allocators.realloc(ptr, size);
}
void std_free(void *ptr) {
memory_allocators.free(ptr);
}
The struct static struct StdMemoryAllocator_s memory_allocators is started automatically when the application starts, and it point to the default C memory allocators.
if i have defined a global variable(with initialization) in header file, and included this file in two file and try to compile and link, compiler gives linking error
headers.h:
#ifndef __HEADERS
#define __HEADERS
int x = 10;
#endif
1.c:
#include "headers.h"
main ()
{
}
2.c:
#include "headers.h"
fun () {}
The linker complains because there will be multiple definitions of x once it puts all the object files together to create the executable. You have two different source files including the same header file, and that header file defines a variable x having a value of 10, so you end up with two definitions of x (one in 1.c and another in 2.c).
To avoid multiple definition linker errors, put this in a header file (for example globals.h):
#ifndef GLOBALS_H
#define GLOBALS_H
/*
* The "extern" keyword means that this variable is accessible everywhere
* as long as this declaration is present before it is used. It also means
* that the variable x may be defined in another translation unit.
*/
extern int x;
#endif
Then put this in one source file:
#include "globals.h"
int x = 10;
This is a classic case where you want either the variable declared or declared-and-defined.
If you define it in both source files, you will get a double-definition linker error. One way to handle this is to only set __HEADERS for one of the source files so that it is the one where the variable is defined.
All other source files get the declaration only.
>>headers.h
#ifndef __HEADERS
int x = 10;
#else
extern int x;
#endif
>>1.c
#define __HEADERS
#include "headers.h"
int main (void) {
return 0;
}
>>2.c
#include "headers"
void fun (void) {
}
Of course, it's best to leave definitions out of header files altogether in case you accidentally define __HEADERS in two source files. Try:
>>headers.h
extern int x;
>>1.c
#include "headers.h"
int x = 10;
int main (void) {
return 0;
}
>>2.c
#include "headers"
void fun (void) {
}
#include works exactly the same as if you copied and pasted the text from the header file.
Consider it in that way and you will see that you have therefore put the line int x=10 into both your source files.
A fixed version is below:
>>headers.h
#ifndef __HEADERS
#define__HEADERS
extern int x; // extern tells the compiler it will be linked from another file
#endif
-----------------
>>1.c
#include "headers.h"
int x = 10; // must have it in ONE file for linking purposes
main ()
{
}
---------------------
>>2.c
#include "headers"
fun () {}
Define __HEADERS in the ifndef.
Put declarations, not definitions, in your headers:
// header
extern int x;
// implementation
int x = 10;
3. 2.c has the include wrong.
So:
// headers.h
#ifndef __HEADERS
#define __HEADERS
extern int x;
#endif
// 1.c
#include "headers.h"
int x = 10;
main ()
{
}
// 2.c
#include "headers.h"
fun () {}
You can define x anywhere. Just make it one place.