Field parent has incomplete type - c

I'm new to C, and can't get this program to compile. Here's the relevant portion of code:
typedef struct {
git_odb_backend parent;
redisContext *db;
} hiredis_backend;
Compiling results in an error:
error: field 'parent' has incomplete type
Here's the complete file: https://github.com/libgit2/libgit2-backends/blob/master/redis/hiredis.c
Other answers to similar questions mention a header file. Should there be a hiredis.h file as well?
EDIT git_odb_backend is defined here: https://github.com/libgit2/libgit2/blob/development/include/git2/sys/odb_backend.h

I don't know anything about what git_odb_backend is (and neither does the compiler) so here's my advice.
The file hiredis.c needs to know the full declaration of git_odb_backend to allow you to declare it as a non-pointer member variable. This is because the compiler needs to know things about the git_odb_backend such as: What is its size? How do I construct it? It doesn't need to know the function implementations, just what the struct looks like.
So you need to find the header file that declares git_odb_backed and include that in
hiredis.c.
Or, forward declare it and take a pointer:
typedef struct git_odb_backend git_odb_backend;
typedef struct {
git_odb_backend*parent;
redisContext *db;
} hiredis_backend;

Related

Opaque datatypes and structures in c

I have a very simple question.
If I have a source code file like this:
#include<stdio.h>
#include"example.h"
struct mystructure{
//Data Variables
int a;
};
int main(){
mystructure somename;
somename.a = 1;
printf("%d\n", somename.a);
return 0;
}
With a header file like this:
#ifndef EXAMPLE_HEADER_H
#define EXAMPLE_HEADER_H
// Opaque declaration.
struct mystructure;
typedef struct mystructure mystructure;
#endif
The code will compile fine. I could also define the structure in the header file and it will compile fine.
However, if I define the structure in a different source code file and attempt to compile it with the main source code file it will keep throwing errors about forward declarations.
Is there a way to define a structure in a source code file give it a typedef in a header file and use it elsewhere in other source files?
I have been doing this awhile now by defining the structure in the header file, but I would like to know how to do this in a more opaque way.
To perform this declaration and statement
mystructure somename;
somename.a = 1;
the compiler needs to know the complete definition of the structure struct mystructure. For instance it needs to know how much memory to allocate for the object somename and whether the structure has the data member a.
So the definition of the structure must be visible in the module with main where these declaration and statement are present.
To hide the structure definition you could declare a pointer of the type struct mystructure * and call functions to initialize this pointer and data members of the pointed object. The corresponding functions must know the structure definition.

Problem with C nested structure. error: invalid use of incomplete typedef

For the sake of simplicity I'm going to recreate the actual situation with dummy structures. I have this structure (not my code, I can't edit it):
// private_header_a.h
struct A_s{
int a1;
};
// header_a.h
typedef struct A_s A_t;
Then in one of my headers I extended it this way:
// my_header.h
typedef struct B_s{
A_t* a_f;
int b1;
} B_t;
Now, in my function, I have:
B_t* b;
// Initialization and some other code
b->b1 = 4; // Just an example and compiler does not give any error
// Some other code
b->a_f->a1;
This last line of code makes the compiler throw this error:
error: invalid use of incomplete typedef ‘A_t’ {aka ‘struct A_s’}
Where is the error?
EDIT: the piece of code that triggers the compiler has header_a.h and my_header.h included. private_header_a.h cannot be included directly as not installed (I should copy-paste it, but frankly I would like to avoid to do that)
The compiler error is probably intentional - the library's designers don't want you using A_t directly in that sort of way.
When a struct is only declared in a library's public header file, and only defined in the library's private implementation files, that means you're not supposed to know or care about its members or even size. So looking up that the struct has a member named a1 and writing b->af->a1 is not the intended use. This arrangement is called an "opaque handle". A few of its benefits are that the library keeps your application code from initializing or changing members in ways that don't make sense, and a future version of the library can change the names, numbers, and meanings of the members without breaking your application code.
(Also, how did you get a valid pointer for b->af without doing malloc(sizeof(A_t)) or similar? That sizeof would also cause a compiler error about the incomplete struct type.)
When a library uses an opaque handle, since you can't create any such objects yourself, it will typically provide functions that create the objects for you. Look for public functions in the library with names including init, create, open, etc. which return an A_t* pointer, and read their documentation. Usually there will also be a corresponding destroy, cleanup, close, etc. function which the program should call later when the library object is no longer needed. (In the case of some very simple handles, the function which creates the object might say instead you should just pass the pointer to free. But only do this if the documentation says to!)
Here's two fundamental rules:
Each c file is compiled separately
When you #include a file, think of it as directly replacing the #include line with the contents of the file being included.
Therefore, you are compiling a piece of source code that looks like this:
struct A_s {
int a1;
};
typedef struct B_s {
A_t* a_f;
int b1;
} B_t;
void foo() {
B_t* b;
}
This code doesn't know what A_t is. You've never defined that in the code that's visible to the compiler.
A trivial way to fix this is to replace A_t with struct A_s.

typedef'd struct not found by header

I'm sure its something very foolish, but I'm stumped:
I have a typedef'd struct declared in one header:
Firstheader.h
typedef struct Pin
{
uint8_t a;
uint8_t b;
} PinStruct;
I then want to use this typedef'd struct in a function declaration in another header:
Secondheader.h
#include "Firstheader.h"
void foo (const PinStruct *myPin);
Despite the typedef'd struct being clearly defined in the first header, and including the first header in the second header, the compiler complains that the "identifier PinStruct is undefined". Someone please smack me and tell me what I'm missing.
EDIT: Thanks for the comments guys. The compiler is marking the function declaration in the second header as the source of the error. The exact error is just as I wrote: Error[Pe020]: identifier "PinStruct" is undefined.
What's strange is if I copy the struct definition into the Secondheader.h header file, the compiler immediately complians about a re-definition of the struct. So it knows its there.
Your code should work perfectly fine (tested with both GCC and CLANG).
You are defining your structure within your typedef and aliasing it to PinStruct -- no errors.
You include the first header file -- no errors.
You use PinStruct in your function declaration of foo -- no errors.
The error could be in your C source file, have you included the header file of "file 2" in the C source file of "file 2"? Example:
// File file_1.h
typedef ...
... and:
// File file_2.h
#include "file_1.h"
// Function declaration.
... and lastly (error here):
// File 2.c
#include "file_2.h" // Forgot?
The syntax is fine. Make sure you don't have grammar errors anywhere. Also when you are prototyping, you don't need to declare the variable name there. You can just do
void foo(const PinStruct *);
You haven't provided enough information, so your question should be closed, but what this usually means is that FirstHeader.h somehow ends up including SecondHeader.h before PinStruct gets declared - i.e. a circular dependency.
You can solve it by declaring PinStruct in SecondHeader.h, using a so-called forward declaration:
typedef struct Pin PinStruct;

What data type needed to receive value from this function?

I need help figuring out the correct data type for an assignment from a function call please.
I'm trying to get at the data in the content field of N_Vector u. Here's what the documentation says about N_Vector:
The type N_Vector is defined as
N_Vector u;
tpedef struct _generic_N_Vector *N_Vector;
struct _generic_N_Vector {
void *content;
struct _generic_N_Vector_Ops *ops;
};
...
[The parallel NVECTOR module] defines the content field of N_Vector
to be a structure containing global and local lengths, a pointer to the
beginning of contiguous local data array, MPI communicator and flag.
struct _N_VectorContent_Parallel {
long int local_length;
long int global_length;
booleantype own_data;
realtype *data;
MPI_Comm comm;
}
So I guess that means that content in _generic_N_Vector "points to" a structure of type _N_VectorContent_Parallel (right?).
Then I try to use a macro for accessing content. Here's the documentation for NV_CONTENT_P.
v_cont=NV_CONTENT_P(v) sets v_cont to be a pointer to the N_Vector content
structure of type struct _N_VectorParallelContent.
Notice the different name of the struct!
What does that mean? What type do I declare v_cont to be?
I tried
N_Vector u;
...
_N_VectorParallelContent *v_cont1;
_N_VectorContent_Parallel *v_cont2;
v_cont1 = NV_CONTENT_P(u);
v_cont2 = NV_CONTENT_P(u);
but these declarations got the error "'_N_VectorContent_Parallel' undeclared..." or "'_N_VectorParallelContent' undeclared...".
But it seems that these structures must be delcared already. I successfully declared (and used) u, of type N_Vector. And the docs seem to say that N_Vector contains one of those two structures (or maybe both).
So why the error message? What is the correct data type to declare for v_cont to receive data from NV_CONTENT_P?
I know this is a long, detailed question, but I don't understand enough to whittle it down any more.
Thanks for your help.
I'm not familiar with this particular library, but it looks to me like the documentation is a little inconsistent.
Right after the blurb about NV_CONTENT_P(v), it says NV_CONTENT_P(v) is defined as:
#define NV_CONTENT_P(v) ( (N_VectorContent_Parallel)(v->content) )
So that version of the name is probably correct. I can't see a definition for N_VectorContent_Parallel on that page, but it's probably defined somewhere as something like struct _N_VectorContent_Parallel*. So, you can probably do:
N_VectorContent_Parallel v_cont1 = NV_CONTENT_P(u);
Remember that for structs, struct is part of the type name. This means that you're getting errors in your example because you haven't included struct:
// this is an unknown type
_N_VectorParallelContent *v_cont1;
// this is a "struct _N_VectorParallelContent"
struct _N_VectorParallelContent *v_cont1;
// But use this one, as it follows the macro
N_VectorContent_Parallel v_cont1;
If you want to see exactly what the preprocessor has done to your code, you can use gcc's -E flag.
-E Stop after the preprocessing stage; do not run the compiler proper.
The output is in the form of preprocessed source code, which is sent to
the standard output.
Input files which don't require preprocessing are ignored.
This is especially useful for seeing the results of macros and multiple complex header files.
Edit: From the source you've linked:
typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel;
This is a type definition that says that N_VectorContent_Parallel is the same as a struct _N_VectorContent_Parallel * (a pointer to a struct _N_VectorContent_Parallel), which means you can access v_cont1 using the -> syntax:
N_VectorContent_Parallel v_cont1;
printf("%d",v_cont1->local_length);
a->b is is shorthand for (*a).b - it's just a cleaner-looking way of writing the dereference needed to accessing a member of a struct through a pointer to that struct. If that seems confusing, see my answer to this question.
Personally, I don't like typedefs that hide pointers like this one, because it's hard to tell by looking at the code whether you need to use a.b or a->b.

How to use pointers to structures

I have defined a structure in one of my source code files. Also I have defined pointer to that structure like (global declaration)
struct blockPropStruct
{ int random_id;
int id;
CvPoint left_up;
CvPoint right_down;
};
typedef struct blockPropStruct *newBlock;
In the same file I am assigning memory to those pointers using malloc to create array of structures.
newBlock = (blockPropStruct*)malloc(maxNum*sizeof(blockPropStruct));
Now I am trying yo use it in some other source file by declaring (global declaration)
extern struct blockPropStruct *newBlock;
Now when I use something like
newBlock[i].left_up.x=mark1[i];
It throws up an error.
It would appear that you have omitted the declaration of the struct type in the file which declares the extern variable.
The name of your structure is struct blockPropStruct. Note that in C, you can't just remove the struct part, it's part of the type's name. You can define a type for your structure so you have less typing, but I think it's better to remember to use your structures as struct blockPropStruct.
Based on the error messages you have added in your comments:
error C2036: 'blockPropStruct *' : unknown size
error C2027: use of undefined type 'blockPropStruct'
You are attempting to get the size sizeof(blockPropStruct) in your malloc() call since blockPropStruct is not a valid identifier so you are attempting to get the size of an undefined type.
To define your type:
typedef struct blockPropStruct blockPropStruct;
Now you can refer to your structure type as blockPropStruct or struct blockPropStruct.
You need to give a name with 'typedef' and point to it.
newBlock = (blockPropStruct*)malloc(maxNum*sizeof(blockPropStruct));
To actually for the above statement to work, the current source file should see the size of structure. So, check whether you have included the corresponding header file.
extern struct blockPropStruct *newBlock;
And when you are doing -
newBlock[i].left_up.x=mark1[i];
You should bring the definition of the blockPropStruct to the current compilation unit to be able to use it members. So, try -
#include "blockPropStruct.h"
extern struct blockPropStruct *newBlock; // This says to use else where
// initialized newBlock
// ....
newBlock[i].left_up.x=mark1[i]; // And to do this, bring the definition
// to this file scope
And there is no need to explicitly typecast malloc.

Resources