Calling C functions in main with struct interfaces and additional C files - c

I have implemented a header file, "msg_queue.h" into a non-main file called "msg_queue.c." From here I created a main file known as "mq_test.c" whereby I created a message queue and called functions that were implemented in "msg_queue.c." Yet, when I run the 'make' command I seem to get this error for each function called:
"enqueue", referenced from:
_main in test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [qmsgtest] Error 1
What seems to be the problem, have I not implemented the structs correctly?
The headerFile:
#ifndef MessageQueue_H
#define MessageQueue_H
typedef struct node{
int data;
struct node *next;
} Node;
typedef struct {
Node *front;
Node *rear;
} MessageQueue;
void enqueue(...); // enqueue
...
#endif //MessageQueue_H
The file implementing the header:
#include "MessageQueue_H.h"
#ifndef MessageQueue_H
#define MessageQueue_H
/* Interface for integer MQueue */
typedef struct node{
int data;
struct node *next;
} Node;
typedef struct {
Node *front;
Node *rear;
} MQueue;
void enqueue(... ){ // enqueue
....

In the file implementing the header, msg_queue.c, you have an include guard:
#ifndef MSG_QUEUE_H
#define MSG_QUEUE_H
You have an include guard with the same name in msg_queue.h and as the header is preprocessed first, the implementation code is removed by the preprocessor (because MSG_QUEUE_H is already defined, your include guard is removing the implementation code), which is why it can't find the symbols.
You can check this yourself by running gcc or clang with the -E option on your source code. It will show you what the preprocessor has done to your code (which in your case means that you get only the prototypes of the functions, not the implementations).
So you need to remove the include guard in your .c source file.
It's worth noting that include guards aren't normally needed in .c implementation files, as these normally aren't included from other files.
In your example, you've also defined your struct types twice (both in the header and in the C file). This violates the single definition rule, so if you want to define your interface with the data types in the header, you should remove them from the source file, otherwise it won't compile.
There are other errors in this code which prevent it from compiling (at least in C99 mode which is what I've tested it as), but these are unrelated to your problem with the linker not being able to find the function symbol(s).

Related

malloc a struct in kernel header file error :invalid application of 'sizeof' to incomplete type

I'm new to linux.
I'm practice syscall and I want to copy struct to user.
So I write a syscall which is using copy_to_user().
But When I write and compile test.c to test my syscall appear some error.
in linux/sched.h has defined:
struct pacct_struct {
int ac_flag;
long ac_exitcode;
unsigned long ac_mem;
cputime_t ac_utime, ac_stime;
unsigned long ac_minflt, ac_majflt;
};
and then I write a program that use this struct(test.c)
#include "linux/sched.h"
#include <stdlib.h>
int main(){
struct pacct_struct *ts;
ts = (struct pacct_struct *)malloc(sizeof(struct pacct_struct));
return 0;
}
and gcc show the follow error message:
test.c:6:44: error: invalid application of 'sizeof' to incomplete type 'struct pacct_struct'
I wonder to know if it's fine to use kernel struct by include header file.
If so, do I miss something? How to make pacct_struct become a 'complete type'?
thanks.
addition:
I check preprocessor with gcc -E
I found that seems no "struct pacct_struct" being included.
Next, I going to view sched.h that I included which was created by "make headers_install" after I compile the kernel.
The file only contains some cloning flags such like "#define CSIGNAL 0x000000ff"
So, I tried to include original source file of sched.h in dir "/usr/src/linux-2.6.39.4/include/linux", but it continue showing same error 'incomplete type'.
Then I check preprocessor again.
I still can't find 'struct pacct_struct' even I include original header file
Anything in sched.h after #ifdef __KERNEL__ is disappear, What happened?

Compile the same C code for user space as well as kernel space

lets say i have a .h and .c file, originally written for kernel space.
#ifndef __TREE_H__
#define __TREE_H__
/* #includes for kernel headers*/
struct tree_node_t{
int data;
struct tree_node_t *left;
struct tree_node_t *right;
};
struct tree{
int data;
struct tree_node_t *root;
};
void insert_node(struct tree *tree, int data);
#endif
Lets say, the corresponding .c file contains the definition of void insert_node fn, which create a tree_node using kmalloc() and insert it into a tree. I am able to compile the code using Makefile to compile the kernel modules as the .h/.c file are part of kernel module.
Now, i want to use the same data structure and its fns in userspace as well. I need to compile it using new user space specific makefile which takes care to replace the kernel specific calls like kmalloc and kfree with malloc and free instead ? How can i use various combination of #ifdef #else #endif so that the files are compilable in user space and kernel space by using respective make files.
pls Nte : kmalloc/kfree are just simple examples to explain. Files contain other kernel specific APIs which needs to be excluded/replaced at the time compilation of file in user space.
You may use __KERNEL__ macro for differentiate target of compilation: kernel code (macro is defined) or application (macro is not defined).
Exactly this macro is used in Linux kernel for uapi headers and some other files. See, e.g., include/uapi/linux/ethtool.h.

libwebsockets: Dereferencing pointer to incomplete type error

I'm using libwebsockets and I can't compile a demo code implemented by myself.
I created the context:
struct libwebsocket_context *context;
...
context = libwebsocket_create_context(&info);
and when I try to access the members of the struct libwebsocket_context, defined in private-libwebsockets.h:
struct libwebsocket_context {
struct pollfd *fds;
struct libwebsocket **lws_lookup; /* fd to wsi */
int fds_count;
int max_fds;
int listen_port;
...
};
For example,
printf("%d\n", context->listen_port);
The compiler returns,
error: dereferencing pointer to incomplete type
Thanks!
It seems that "struct libwebsocket_context" is not known for gcc - that's why this error occures. Are you sure that definition of this structure is included from .h file? I'd suggest you to insert for example #warning or #error with some message near definition of this struct (in .h file) and try to recompile your program. Your #error or #warning message should appear while compilation. If not - it means that gcc will not also see this struct.
The fact that the struct definition is in private-libwebsockets.h suggests that you are not supposed to use the struct members directly. You can #include that header to get access to the private implementation details of the library but you probably should not do it.

How to use multiple source and header files

I recently learnt how can we use multiple source files with header files to make code portable and hierarchical. In order to do so, I tried to create my tree program using this principle. Here are my files
b_tree_ds.h - This will contain a declaration of datastructure of node of a tree, which can be called to various functions implementing different functionality of the tree (which may be in different source files)
typedef struct node {
struct node* left;
struct node* right;
int key; // contains value
}NODE;
When i try adding a extern as in typedef extern struct node it gives a error of multiple storage class but if I miss it, I get error for multiple definitions.
Here are my other source files
traverse.h - contains declaration of traverse function
void traverse_print (NODE* p);
Here also I get error for unknown identifier NODE
traverse.c - contains definition to that function
#include <stdio.h>
#include "b_tree_ds.h"
#include "traverse.h"
void traverse_print(NODE* p)
{
if(p->left != NULL)
{
traverse_print(p->left);
}
if (p->right != NULL)
{
traverse_print(p->right);
}
printf ("\n%d",p->key);
}
Finally main.c
#include <stdio.h>
#include "traverse.h"
void main()
{
// input
NODE p;
printf("\nInput the tree");
input_tree (&p);
printf("\n\nThe tree is traversing ...\n")
traverse_print(&p);
}
void input_tree (NODE *p)
{
int in;
int c;
NODE *temp;
printf("\n Enter the key value for p: ");
scanf("%d", &in);
p->key =in;
printf ("\n\nIn relation to node with value %d",in);
printf ("Does it have left child (Y/N): ")
if ((c = getchar()) == Y);
{
//assign new memory to it.
temp = (NODE *)malloc(sizeof(NODE));
input_tree(temp);
}
printf ("\n\nIn relation to node with value %d",p->key);
printf ("\nDoes it have right child (Y/N): ")
if ((c = getchar()) == Y);
{
//assign new memory to it.
temp = (NODE *)malloc(sizeof(NODE));
input_tree(temp);
}
}
This is my first attempt to such practice, please suggest is the structuring of my program good or should I try something else.
You may be having problems because you haven't yet got a strong reason to split things up. A good reason would help you identify which parts belong together, and which parts are separate. So start with a simpler approach.
Split the program into three files, main.c, which contains main(), node.h, the header which ensures declarations are common across all the program, and hence is understood by the compiler, and node.c, the functions which manipulate the NODE structure.
Put the typedef ... NODE; and all the declarations of functions which manipulate NODE into one the node.h header file. So you could merge the existing header files into one, and call it node.h.
As Joop Eggen recommends, put #ifndef _NODE_H_ ... #endif around node.h contents to protect it against accidentally being #included twice.
Test that file is correct with a minimal main.c file containing:
#include "node.h"
int main() { return 0; }
and compile it. That should give no compilation errors. If it contains errors the fault is in the header file.
Put the functions that manipulate NODE, into a file called node.c, which will initially be:
#include "node.h"
compile and link that with main.c (gcc main.c node.c), and there should be no errors.
Build up the program is stages, adding code to the main.c file, the node.c file, and add declarations of functions in the node.c file into node.h. Add small amounts of code, and compile frequently (with warnings switched on, e.g. gcc -Wall main.c node.c) and test to make sure it is doing what you expect.
The program will eventually be complete.
I recommend looking at What are extern variables in C?.
You can include system headers such as <stdio.h> without having to worry about whether there are other headers needed to make use of its services. You should design your own headers in the same way. You should also prevent errors if your file is included multiple times (whether accidentally or deliberately).
You have:
b_tree_ds.h
typedef struct node {
struct node* left;
struct node* right;
int key; // contains value
} NODE;
Up to a point, this is fine; you just need to wrap it in header guards so reinclusion does no damage.
#ifndef B_TREE_DS_H_INCLUDED
#define B_TREE_DS_H_INCLUDED
typedef struct node {
struct node* left;
struct node* right;
int key; // contains value
} NODE;
#endif /* B_TREE_DS_H_INCLUDED */
You note:
When I try adding extern as in typedef extern struct node it gives a error of multiple storage class but if I miss it, I get error for multiple definitions.
Syntactically, extern, static, auto, register and typedef are all storage classes, and you can only have one storage class in a given declaration. That's why you get the multiple storage class error. The 'multiple definition' error will continue to be a problem until C2011 is widespread, and the header guards prevent that from being a problem. I think header guards will remain valuable even after C2011 is widely available.
traverse.h
void traverse_print (NODE* p);
As it stands, you can't simply write #include "traverse.h" to make use of its facilities. This is something to be avoided whenever possible. (See: Self-sufficent header files in C and C++,
What is a good reference documenting patterns of use of h files in C, and Should I use #include in headers.) Therefore, this should include b_tree_ds.h:
#ifndef TRAVERSE_H_INCLUDED
#define TRAVERSE_H_INCLUDED
#include "b_tree_ds.h"
extern void traverse_print(NODE *p);
#endif /* TRAVERSE_H_INCLUDED */
You could omit the header include guards on this header (assuming that b_tree_ds.h is self-protects), but it is simpler to be self-consistent in all headers.
There is one other possible technique that could be mentioned:
#ifndef TRAVERSE_H_INCLUDED
#define TRAVERSE_H_INCLUDED
typedef struct node NODE;
extern void traverse_print(NODE *p);
#endif /* TRAVERSE_H_INCLUDED */
This makes NODE into an opaque type; the user of the header traverse.h knows nothing about what's in a NODE. There are coordination issues to resolve that make this a less commonly used technique.
With these changes to the headers, then:
traverse.c only needs to include traverse.h (and should arguably include it before any other header to provide an automatic test of self-containment), but
If traverse.c includes both headers, there are no problems, regardless of the order in which they are included (and it doesn't matter if the repetition is direct or indirect).
Your main.c can include just traverse.h as shown and will be OK. With the original code, because main.c only included traverse.h and traverse.h did not include b_tree_ds.h, the code would not compile properly.
Forget about extern. In traverse.h you should include b_tree_ds.h. Some compilers have a pragma include once, but it does not hurt to surround the content of b_tree_ds.h with:
#ifndef B_TREE_DS_H
#define B_TREE_DS_H
...
#endif // B_TREE_DS_H
Look for compiler info on this case, and also on precompiled headers.
The above is a platform independent way of excluding content the second time.

Defining self-referential structs in a C header file (.h)?

I'm trying to create a struct used in two .c source files to make a simple linked list structure. I thought it would save time to create a struct in the header file, however, I get a 'parse error before *' error.
This is the code I'm using:
/*
* Structures.h
*
* Created on: Dec 17, 2011
* Author: timgreene
*/
#ifndef STRUCTURES_H_
#define STRUCTURES_H_
typedef struct list_struct {
int data;
struct list_struct* next;
struct list_struct* prev;
} list;
#endif /* STRUCTURES_H_ */
Edit: I did originally omit a detail that is, I'm actually compiling with xcc from the XMOS toolchain. I still don't understand that there would be a difference in .h file syntax.
Could it be a compilation flag I'm using?
Here's the console printout:
xcc -O0 -g -Wall -c -MMD -MP -MF"filter.d" -MT"filter.d filter.o " -target=XC-1A -o filter.o "../filter.xc"
In file included from ../filter.xc:15:
Structures.h:13: error: parse error before '*' token
Structures.h:14: error: parse error before '*' token
Structures.h:15: error: parse error before '}' token
Looking around in some of the XMOS documentation, it seems the problem is that XC is not C, it's just a C-like language. From the "XC Programming Guide":
XC provides many of the same capabilities as C, the main omission being support
for pointers.
...which explains why it doesn't accept the next and prev pointers in your structure.
Apparently xcc lets you mix C and XC sources, though, so if you were to limit your use of the structure to C code it should work. From the "XCC Command-Line Manual", it appears that anything with a .xc extension (as in the command line you used above) is treated as XC, rather than C, source code by default. This can be overridden by placing the option -xc before the C sources on the command line and -x afterward (or just rename the files with a .c extension).
If you must use XC rather than C, you may need to find another way of doing things (arrays, maybe?).
Try using a forward declaration of struct list_struct:
struct list_struct;
typedef struct list_struct {
int data;
struct list_struct* next;
struct list_struct* prev;
} list;
Perhaps your compiler doesn't recognize the identifier in the middle of its own definition, I'm not sure what the standards say about that (if anything).
For those that don't already know, this is also the way to deal with circular dependencies in struct definitions:
struct a;
struct b;
struct a {
int x;
struct b *y;
};
struct b {
int x;
struct a *y;
};

Resources