I am pretty new to C and have the following issue with a framework specific datatype that is used within an extern declared function for a parameter inside a header file.
//FILE: example.h
extern void my_function(void *);
//FILE: example.c
#include "example.h"
#include "freertos/task.h"
void my_function(TaskHandle_t _taskHandle){
//function body
}
The datatype TaskHandle_t
is of course not known in the header as I would have to include the freertos header here as well. I heard including other header files inside a header file is bad practise.
If I try to compile the example above the following error raises:
error: conflicting types for 'my_function'
void my_function(TaskHandle_t _taskHandle)
Whats the best approach to solve this problem?
CodePudding user response:
Very much in contrast to the best practice you mention, I follow what I consider a rule:
"Include what you need. Do not include what you do not need."
I am very much with M. Oehm:
If a header file requires definitions from other header files, it should include that header. It sure isn't any worse practice than trying to work around it by using void *.
The concept of forward declaring structs allows to use pointer-to-that before including or typedefining the struct in detail. (As mentioned in the comment be some programmer dude.)
CodePudding user response:
Declaring an otherwise unknown datatype is about the only good reason why you should include a header in a header. However there is also the so-called 'forward declaration', which you can use when you need to pass a pointer to a struct. (Or class in C )
A forward declaration simply looks like this:
//.h file
struct YourType;
void yourFunction(struct YourType *variable);
//.c file
#include "HeaderContainingYourType.h"
void yourFunction(struct YourType *variable)
{
}
As for your specific problem, your prototype and your declaration must have the exact same signature, so if you declare the prototype with void *
, you must use void *
in the declaration too.
Ways to solve your problem:
- Include the header file you need.
- Pull out the typedef from the header file and redeclare it verbatim in your new header file.
- Pass
void *
and cast it to the appropriate type in the C file.
Please note, that the third approach negates the aspect of 'typesafety', since you can pass anything to a void *
.
CodePudding user response:
If TaskHandle_t
is a pointer to struct then you can forward declare the struct and add an alias for a pointer to it.
typedef struct TaskHandle_s *TaskHandle_t;
void my_function(TaskHandle_t _taskHandle);