struct in header compilation error - c

I'm trying to write a framework library which wraps MPI.
I have a header file for the framework call afw.h and an implementation file for the framework called afw.c.
I would like to be able to write application code which uses the framework by doing #include "afw.h" in the application code.
An excerpt from afw.h:
#ifndef AFW_H
#define AFW_H
#include <mpi.h>
struct ReqStruct
{
MPI_Request req;
};
ReqStruct RecvAsynch(float *recvbuf, FILE *fp);
int RecvTest(ReqStruct areq);
I provide an implementation for RecvAsynch in afw.c which #includes afw.h
When I compile using mpicc (an MPI compiler wrapper in this case using pgc underneath):
mpicc -c afw.c -o afw.o
I get:
PGC-S-0040-Illegal use of symbol, ReqStruct (./afw.h: 69)
PGC-W-0156-Type not specified, 'int' assumed (./afw.h: 69)
PGC-S-0040-Illegal use of symbol, ReqStruct (./afw.h: 71)
PGC-W-0156-Type not specified, 'int' assumed (./afw.h: 71)
and similar errors wherever ReqStruct is used in afw.c
Any ideas what I am doing wrong?

You defined a struct ReqStruct, not ReqStruct, and those are not the same thing.
either change the function to
struct ReqStruct RecvAsynch(float *recvbuf, FILE *fp);
or use typedef:
typedef struct ReqStruct ReqStruct;

In C++, the sequence:
struct ReqStruct
{
MPI_Request req;
};
defines a type ReqStruct that you can use in your function declaration.
In C, it does not (it defines a type struct ReqStruct that you can use); you need to add a typedef such as:
typedef struct ReqStruct
{
MPI_Request req;
} ReqStruct;
Yes, the struct tag can be the same as the typedef name. Or you can use struct ReqStruct in place of just ReqStruct everywhere; I'd use the typedef in preference.

Related

struct declared in tools.h and defined in tools.c. Can't link them to main.c

file tools.h:
//some macro definitions
struct name;
//other function prototypes
file tools.c:
#include "tools.h"
struct name
{
FILE *src;
int value;
}
//definitions of functions declared in tools.h
file main.c:
#include <stdio.h>
#include "tools.h"
int main()
{
struct name *ptr;
ptr = malloc(sizeof(struct name));
ptr->FILE = fopen(filename, "r");
ptr->value = 12;
...
}
At first, I built tools.o by using:
$ gcc tools.c -c
Without any error or warning, tools.o was built in the current directory.
Now, I tried to build executable by using:
$ gcc main.c tools.o -o exe
and I got errors of same type (all the errors were of same type, caused due to accessing the struct element). Here's the sample of that error I got:
main.c: In function ‘main’:
main.c:17:22: error: invalid use of undefined type ‘struct name’
17 | buffer = malloc(ptr->value+1);
Please explain why this happened and what wrong I did while linking or in my code.
tools.h file
#ifndef TOOLS_H
#define TOOLS_H
#include <stdio.h>
struct name
{
FILE *src;
int value;
};
int foo(struct name*);
struct name *bar(double, FILE*, const char *); //prototypes of functions defined in tools.c
#endif
tools.c
#include "tools.h"
int foo(struct name*)
{
/* ... */
}
struct name *bar(double, FILE*, const char *)
{
/* ... */
}
Looks like you have some confusion with regards to forward declaration of a structure and a structure declaration (which defines a type).
From Forward declaration:
a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.
In tools.h, this
struct name;
is forward declaration of structure struct name. Note that, it declares an incomplete type because the specification [list defining the content] of struct name is unknown at this time.
You have included the tools.h in main.c and when compiling main.c compiler does not find the specification of struct name and hence, throwing error on the statements using it.
In tools.c, you are declaring the struct name (which defines a type):
struct name
{
FILE *src;
int value;
};
when compiling tools.c, compiler knows about the specification of structure struct name and hence, it's compilation is successful.
The other post [by #0___________] gives the appropriate way to solve this problem.

How to include array of struct defined in another header in C?

I have the below files:
swaps.c:
#include "swaps.h"
#include "./poolutils.h"
double someFunction(struct Pool pools[]){
//do some stuff
}
int main(){
struct Pool pool1 = {"A","C",3.0,9000.0,0.0};
struct Pool pool2 = {"B","D",20.0,20000,0.0};
struct Pool pools[N];
pools[0] = pool1;
pools[1] = pool2;
double a = someFunction(pools);
}
swaps.h has signature of someFunction
poolutils.c has some functions
poolutils.h:
#ifndef _POOLUTILS_H
#define _POOLUTILS_H
struct Pool {
char *token1;
char *token2;
double reserve1;
double reserve2;
double fee;
};
//signatures of poolutils.c functions
#endif
When compiling (gcc -c swaps.c poolutils.c), I am getting the below error:
In file included from swaps.c:1:
swaps.h:4:44: error: array type has incomplete element type ‘struct Pool’
4 | double someFunction(struct Pool pools[]);
Now, I do include the header where the struct Pool is defined, so swaps.c should know about it but I understand that somehow swaps.h does not, how can I make it aware of the outside definitions ?
(gcc version 10.2.1 20210110 (Debian 10.2.1-6))
Simply add
#include "./poolutils.h"
to your swaps.h too, if swaps.h needs the Pool struct definition.
Since you've dutifully put include guards in poolutils.h, you can use the header multiple times in a single compilation unit.
Alternately, swap the order of your includes; the effect is the same here.
#include "./poolutils.h"
#include "swaps.h"

Forward declaration issue, two compilers

I've been developing in C using eclipse as my IDE in my virtual machine with ubuntu, I've made some progress and I wanted to test them in the real product which is an embedded system using powerpc.
In order to compile that program for our product I use Code::Blocks in Windows but the compiler is a powerpc version of the gcc.
The same code is giving me an error in the powerpc version that doesn't appear in the ubuntu version.
I have two header files gral.h and module_hand.h as follows:
The gral.h file:
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
#include "module_hand.h"
typedef struct PROFILE
{
module_t mod; // this one comes from module_hand.h
int var1; // some other random variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */
The module_hand.h is defined as follows
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <stdint.h>
#include "gral.h"
typedef struct PROFILE profile_t;
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
int Mod_Init(profile_t *profile);
/* some other random functions */
#endif /* HEADERS_MODULE_HAND_H_*/
As you'll see, I don't use the PROFILE struct in the module struct, But I declare it forward to use it in the declaration of the Mod_Init function
This gives me a Error: redefinition of typedef 'profile_t'
and error: previous declaration of 'profile_t' was here
If I remove the forward declaration the error is Error: parse error before '*' token
where the line number is the line of the function declaration.
My doubt is what am I missing, and why gcc in Ubuntu does compile it with no problem.
Your powerpc compiler is enforcing the C99 rule that
If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier) with
the same scope and in the same name space, except for tags as
specified in 6.7.2.3.
(C99 6.7/3)
Your Linux compiler is observing the relaxed version of that rule that was introduced in C11:
If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier) with
the same scope and in the same name space, except that:
a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
tags may be redeclared as specified in 6.7.2.3.
(C11 6.7/3; also C17 6.7/3)
Supposing that the compilation options are the same, the behavior difference surely arises from using different versions of GCC. More recent versions default to more recent versions of the language.
You could try adding -std=gnu11 or -std=c11 to the command-line options (for both targets) to try to get consistency. If your powerpc version of GCC is too old to accept those then you really need to update to a newer version.
Note also, however, that you don't need to have this problem in the first place. Given that module_hand.h includes gral.h, the former has no need whatever to redefine a typedef that the latter already defines.
Moreover, the fact that these two headers each include the other is a strong suggestion that they ought to be combined into one. Multiple-inclusion guards prevent an actual loop, but they are not an adequate solution.
In the gral.h header file, you define profile_t using typedef, then you redefine profile_t with another typedef in module_hand.h. You should just define the struct PROFILE in gral_h and include gral.h in module_hand.h.
gral.h:
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
#include "module_hand.h"
typedef struct PROFILE {
module_t mod; // this one comes from module_hand.h
int var1; // some other random variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */:
module_hand.h:
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <stdint.h>
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
int Mod_Init(struct PROFILE *profile);
/* some other random functions */
#endif /* HEADERS_MODULE_HAND_H_*/
Well I read your answers and comments and decided to try another approach.
As some of you said, I had some kind of recursion, I wanted to keep every structure within its respective header file, but now, I dropped the idea and merged the structures in one file only.
My new approach:
Gral.h
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
typedef struct PROFILE {
module_t mod; // this one comes from module_hand.h
int var1; // some other variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */:
Module.h
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <Gral.h>
int Mod_Init(profile_t *profile);
/* some other functions */
#endif /* HEADERS_MODULE_HAND_H_*/
And when any other structure comes up, I'll declare it in Gral.h and include the header file.
Regarding the compilers, they aren't the same version. The powerpc is quite old now. That would explain the powerpc compilation errors.
Thank you again.

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.

Managing and handling multiple abstract data types in C with type safety?

I have several hardware signals that get toggled based on properties relevant to scenarios in which respective signals could be toggled. The problem is that signals and the properties that define scenarios, all three could change. I am forced to think in terms of a modular framework based design in which there is SignalManager that handles signal creation and there is a SignalPropertiesData with its SignalPropertiesDataManager that associate certain SignalScenario structure and all this is created specifically for any type of signal by the SignalManager. I wish to follow the public interface, private data in the C programming paradigm.
My dilemma is C in general when it comes to type safety and this kind of problem, the only solution is to lose type safety and use 'void' for any and all types of data. Can you point me to any code or component in the vast opensource sea, which can serve as a right reference for this problem.
signal_manager.h:
#ifdef _SIGNAL_MANAGER_H
#define _SIGNAL_MANAGER_H
int createSignal(SignalDescPtr signalDescPtr);
int destroySignal();
typedef struct SignalDesc* SignalDescPtr;
#endif
signal_manager.c:
#include "signal_manager.h"
typedef struct {
char* signalName;
unsigned int signalId;
SignalPropertiesDataPtr signalProperties;
} SignalDesc;
signal_properties_data.h:
#ifdef _SIGNAL_PROPERTIES_DATA
#define _SIGNAL_PROPERTIES_DATA
typedef enum {
SIGNAL_DATA_INT_TYPE,
SIGNAL_DATA_UNSIGNED_INT_TYPE,
SIGNAL_DATA_FLOAT_TYPE,
:
SIGNAL_DATA_UNSPECIFIED_BASIC_TYPE
} eSignalBasicType;
typedef enum {
SIGNAL_DATA_LIST_ARRAY_TYPE,
SIGNAL_DATA_LIST_ADT_TYPE,
:
:
SIGNAL_DATA_LIST_UNSPECIFIED_TYPE
} eSignalComplexType
typdef union {
eSignalBasicType signalBasicType;
eSignalComplexType signalComplexType;
} eSignalType;
typedef struct {
eSignalType signalType;
unsigned int signalDataLen;
} SignalDataValueType;
typedef SignalPropertiesData* SignalPropertiesDataPtr;
result_t setSignalType(..);
result_ getSignalType(..);
result_t setSignalData(..);
result_t getSignalData(..);
result_t setSignalDataLen(..);
result_t getSignalDataLen(..);
#endif
signal_properties_data.c:
#include "signal_properties_data.h"
typdef struct {
SignalDataValueType signalPropertiesDataType;
void* signalPropertiesDataValue;
} SignalPropertiesData;
signal_properties_data_mgr.h:
#ifdef _SIGNAL_PROPERTIES_DATA_MGR_H
#define _SIGNAL_PROPERTIES_DATA_MGR_H
#include "signal_properties_data.h"
#include "signal_scenario.h"
typedef SignalScenarioDesc* SignalScenarioDescPtr;
result_t createSignalPropertiesData(SignalPropertiesDataPtr *signalPropDataPtr, eSignalType desiredSignalType);
result_t freeSignalPropertiesData(..);
result_t associateSignalToggleScenario(SignalPropertiesDataPtr *signalPropDataPtr, SignalScenPtr signalScenPtr);
result_t disassociateSignalToggleScenario(SignalPropertiesDataPtr *signalPropDataPtr, SignalScenarioDescPtr signalScenPtr);
#endif
signal_properties_data_mgr.c:
#include "signal_properties_data_mgr.h"
typedef struct {
toggleFuncPtr fptr;
} SignalScenarioDesc;
Avoid going for void *. It loses the benefits of prototypes and is not necessary,
Since this is C, you should write in signalmanager.h
#ifndef SIGNAL_MANAGER_H_INCLUDED
#define SIGNAL_MANAGER_H_INCLUDED
typedef struct SignalDesc* SignalDescPtr;
int createSignal(SignalDescPtr signalDescPtr);
int destroySignal(void);
#endif
Changes:
Critical: the idiom is #ifndef MACRO / #define MACRO / #endif. You used #ifdef which won't work.
Place typedef before it is used.
Add explicit (void) to make destroySignal(void) into a prototype. Your version simply says 'there is a function destroySignal() that returns an int but it takes an unspecified (but not variadic) argument list'.
Do not use reserved name space (leading underscore, capital letter) for the header protection guard.
I prefer not to hide pointers in data type typedefs, so I'd probably write:
#ifndef SIGNAL_MANAGER_H_INCLUDED
#define SIGNAL_MANAGER_H_INCLUDED
typedef struct SignalDesc SignalDesc;
extern int createSignal(SignalDesc *sigdesc);
extern int destroySignal(void);
#endif /* SIGNAL_MANAGER_H_INCLUDED */
I'm not sure that the interfaces to the create and destroy are correct, but that's another subject for discussion. I'd normally expect to find that the interfaces are more like:
extern SignalDesc *createSignal(const char *name, int signum);
extern void destroySignal(SignalDesc *sigdesc);
The implementation file signal_manager.c would then define the structure type and use it; the external interface is through functions that work with pointers.
#include "signal_manager.h"
#include "signal_properties_data.h"
struct SignalDesc
{
char *signalName;
unsigned int signalId;
SignalPropertiesData *signalProperties;
};
The signal_properties_data.h needs similar cleaning up:
#ifndef SIGNAL_PROPERTIES_DATA_H_INCLUDED
#define SIGNAL_PROPERTIES_DATA_H_INCLUDED
typedef enum {
SIGNAL_DATA_INT_TYPE,
SIGNAL_DATA_UNSIGNED_INT_TYPE,
SIGNAL_DATA_FLOAT_TYPE,
:
SIGNAL_DATA_UNSPECIFIED_BASIC_TYPE
} eSignalBasicType;
typedef enum {
SIGNAL_DATA_LIST_ARRAY_TYPE,
SIGNAL_DATA_LIST_ADT_TYPE,
:
:
SIGNAL_DATA_LIST_UNSPECIFIED_TYPE
} eSignalComplexType
typdef union {
eSignalBasicType signalBasicType;
eSignalComplexType signalComplexType;
} eSignalType;
typedef struct {
eSignalType signalType;
unsigned int signalDataLen;
} SignalDataValueType;
/* Huge hole in types here - or is SignalValueDataType what you're after? */
typedef struct SignalPropertiesData SignalPropertiesData;
result_t setSignalType(..);
result_t getSignalType(..);
result_t setSignalData(..);
result_t getSignalData(..);
result_t setSignalDataLen(..);
result_t getSignalDataLen(..);
#endif /* SIGNAL_PROPERTIES_DATA_H_INCLUDED */
This revised header is not self-contained yet. It does not define result_t, so it should include the header that does. I assume the ... notation in the function calls is "do not want to specify in this question" because it isn't valid in C; you must have one argument of known type before you specify the ellipsis.
It is not clear from the functions in the header why the user of the header needs to know about the types that are defined in it. Think of a header as a resource that will be shared. It 'belongs to' or describes the external interface to a file (or a small set of files). It gives the users the minimum data that they need to use the facilities provided by the code, but no more than the minimum. You sometimes find that a set of files implementing a facility will need a private header to share between themselves as well as the public header that other code ('customer' code or 'consumer' code) uses.
The key to opaque types is that the consumer doesn't need to know the internal details of a structure to be able to use pointers to the structure type (see Which part of the C Standard allows this code to compile?, Does the C standard consider that there are one or two struct uperms_entry types in this header? and How to structure header files in C for some more insight).
I am not sure that I fully understand what your needs are, but I think that you could look at WIN32 handles for a reference implementation.
A short example would be to define a macro that lets you define custom handles like this:
/* example.h */
#ifndef _EXAMPLE_H
#define _EXAMPLE_H
/* Define macro */
#define DECLARE_HANDLE(HandleName) typedef struct HandleName##Tag * HandleName
/* Declare some handles */
DECLARE_HANDLE(SomeHandle);
DECLARE_HANDLE(SomeOtherHandle);
#endif /* _EXAMPLE_H */
/* example.c */
#include "example.h"
struct SomeHandleTag {
int foo;
};
struct SomeOtherHandleTag {
int foo;
};

Resources