Is it possible to hide part of the standard header (in C)?

I want to do something that seems impossible.

I want to write 3 files: main.c , foo.h , foo.c.
The idea is to define a structure in foo.h or foo.c so that its elements are visible in main.c. One member of the structure is of type FILE , as defined in the standard <stdio.h> header. But functions and macros <stdio.h> should remain invisible inside the main.c file.

The solution must comply with C standard (C99 and / or C11) and portable. Is it possible?

The header foo.h is included in both: main.c and foo.c.
The standard header <stdio.h> # is included only in foo.c , but not in main.c.

I want to declare a struct as follows:

 struct myfile_s { FILE *F; char *filename; char buff[100]; } myfile; 

For further, only the member FILE *F is important. The myfile structure will be initialized and modified by the functions displayed in foo.c.
The goal is to perform file operations on myfile through extern functions declared in foo.h , which in turn must be defined in foo.c.

File operations include the standard <stdio.h> functions, but these functions must be hidden in the main.c file. However, I want to get direct access from main.c to myfile members. This would mean that the definition of struct myfile_s should be done in foo.h (that is, it cannot be โ€œdelayedโ€ with the trick of using incomplete structure declarations, such as struct myfile_s ; ).

In short, I would like the FILE type to be visible in main.c and / or foo.h , but keep the rest of the <stdio.h> declarations hidden to them.

Another limitation: the idea of โ€‹โ€‹direct copying at hand is the FILE definition provided by <stdio.h> , which is undesirable because the code must be portable.

My first attempt was to hash a struct myfile by injecting it inside foo.c.
The code was:

foo.h

 struct myfile_s; struct myfile_s myfile; extern void startfile(struct myfile *f); 

foo.c

 #include <stdio.h> #include "foo.h" struct myfile_s { FILE *F; char *filename; char buff[100]; } myfile; void startfile(struct myfile *f) { // Do some stuff... } 

main.c

 #include "foo.h" int main(void) { myfile.F = NULL; // This kind of access bring error, but I want to do it anyway!! startfile(&myfile); return 0; } 

The latency struct myfile_s announces the need to include <stdio.h> in foo.h , so the header works fine, but the structure type remains incomplete, so access to myfile.F cannot do main.c.

So: How can I access myfile.F?

I tried another way, which of course also gives an error:

foo.h

 struct myfile_s { FILE *F; char *filename; char buff[100]; } myfile; extern void startfile(struct myfile *f); 

foo.c

 #include <stdio.h> #include "foo.h" void startfile(struct myfile *f) { // Do some stuff... } 
+7
c
source share
2 answers
 struct myfile_s { void *pPrivateThings; // This could be the FILE* or another private structure char *filename; char buff[100]; } myfile; 

I would highlight another private structure when creating:

 struct myprivatefile_s { FILE *F; // You could add other fields here that are not public } myprivatefile; myprivatefile *privateThings = malloc(sizeof(myprivatefile)); myfile.pPrivateThings = privateThings; privateThings->F = fopen(); 

This way, you can continue to add things that should not be visible (i.e. private) to your heartfelt content.

+7
source share

That everything is uselessly complicated, right?

It sounds like you really don't know what you want. Why do you want to have one copy of myfile in foo.h ? Why do you want to explicitly set myfile.F to main ? Why not write a function like myfile_init for it in foo.c that has full access?

I would make a typedef of an opaque structure in foo.h , define the material and implement the constructor and access functions in foo.h , and then instantiate myfile in main.c :

foo.h

 typedef struct Myfile Myfile; Myfile *myfile_open(const char *filename); myfile_process(Myfile *f, ...); int myfile_close(Myfile *f); 

foo.c

 #include <stdio.h> struct Myfile { FILE *f; ... }; // implement myfile_xxx functions 

main.c

 #include "foo.h" int main() { Myfile *f = myfile_open("rhubarb.txt"); if (f == NULL) exit(1); myfile_process(f, ...); myfile_close(f); return 0; } 

No need to partially include other headers. By moving the initialization to myfile_open everything is neatly encapsulated in foo.c The main program sees only the pens. Just like the standard FILE * descriptors, really.

+6
source share

All Articles