Reputation: 1435
#include <stdio.h>
#ifndef API
#define API
struct trytag;
typedef struct trytag try;
void trial (try *);
#endif
#ifndef CORE
#define CORE
struct trytag
{
int a;
int b;
};
#endif
#include "api.h"
#include "core.h"
void trial (try *tryvar)
{
tryvar->a = 1;
tryvar->b = 2;
}
#include "api.h"
int main ()
{
try s_tryvar;
trial(&s_tryvar);
printf("a = %d\nb = %d\n", s_tryvar.a, s_tryvar.b);
}
When I compile, I get:
main.c:5: error: storage size of ‘s_tryvar’ isn’t known
If I include core.h
in main.c
this error doesn't come as try is defined in core.h
. But I want the structure try
to be hidden to main.c
— it should not know the members of try
structure. What am I missing?
Upvotes: 0
Views: 3984
Reputation: 4055
There is a way to do something that technically is not exactly what you are asking for, but should serve the same purpose of keeping your structure opaque while supporting non-heap allocation.
in api.h, you state an opaque structure as follows:
struct trytag_opaque
{
char data[sizeof(int)*2];
};
if you wanted to be more opaque than that, you could calculate the maximum size of the structure required across any supported platform, and use:
struct trytag_opaque
{
char data[MAX_TRYTAG_SIZE];
};
Then your api.h function declarations would look like:
int try_a(struct trytag_opaque *t)
and your function code would look like:
int try_a(struct trytag_opaque *t_opaque) {
trytag *t = (trytag *)t_opaque;
...
}
and your main.c would look like:
#include "api.h"
int main() {
struct trytag_opaque t;
...
try_a(&t);
...
}
Upvotes: 0
Reputation: 225172
I don't think what you're trying to do is possible. The compiler needs to know how big a try
structure is to compile main.c
. If you really want it to be opaque, make a generic pointer type, and instead of declaring the variable directly in main()
, make alloc_try()
and free_try()
functions to handle the creation and deletion.
Something like this:
api.h:
#ifndef API
#define API
struct trytag;
typedef struct trytag try;
try *alloc_try(void);
void free_try(try *);
int try_a(try *);
int try_b(try *);
void trial (try *);
#endif
core.h:
#ifndef CORE
#define CORE
struct trytag
{
int a;
int b;
};
#endif
func.c:
#include "api.h"
#include "core.h"
#include <stdlib.h>
try *alloc_try(void)
{
return malloc(sizeof(struct trytag));
}
void free_try(try *t)
{
free(t);
}
int try_a(try *t)
{
return t->a;
}
int try_b(try *t)
{
return t->b;
}
void trial(try *t)
{
t->a = 1;
t->b = 2;
}
main.c:
#include <stdio.h>
#include "api.h"
int main()
{
try *s_tryvar = alloc_try();
trial(s_tryvar);
printf("a = %d\nb = %d\n", try_a(s_tryvar), try_b(s_tryvar));
free_try(s_tryvar);
}
Upvotes: 7
Reputation: 76611
The problem is in main.c, the compiler hasn't seen the definition of struct try
. Because of that, the compiler is limited to using pointers to struct try
.
What you want to do is add two new functions to your API:
try *create_try();
void *destroy_try(try *t);
These functions will call malloc and free respectively.
If you don't want to limit your structure to only being allowed on the heap, you are going to have to give up on making it opaque.
Upvotes: 1
Reputation:
Think how the opaque FILE structure works in C. You only work with pointers, and you need a function like fopen() to create an instance, and a function like fclose() to dispose of it.
Upvotes: 1