c - How do I typedef an implementation-defined struct in a generic header? -
i have c project designed portable various (pc , embedded) platforms.
application code utilize various calls have platform-specific implementations, share mutual (generic) api aid in portability. i'm trying settle on appropriate way declare function prototypes , structures.
here's i've come far:
main.c:
#include "generic.h" int main (int argc, char *argv[]) { int ret; gen_t *data; ret = foo(data); ... }
generic.h: (platform-agnostic include)
typedef struct impl_t gen_t; int foo (gen_t *data);
impl.h: (platform-specific declaration)
#include "generic.h" typedef struct impl_t { /* ... */ } gen_t;
impl.c: (platform-specific implementation)
int foo (gen_t *data) { ... }
build:
gcc -c -fpic -o platform.o impl.c gcc -o app main.c platform.o
now, appears work... in compiles ok. however, don't tag structures since they're never accessed outside of typedef
'd alias. it's little nit-pick, i'm wondering if there's way accomplish same effect anonymous structs?
i'm asking posterity, since searched while , closest reply found this: (link)
in case, wouldn't right approach, application shouldn't ever include implementation headers straight -- whole point decouple programme platform.
i see couple of other less-than-ideal ways resolve this, example:
generic.h:
#ifdef platform_x #include "platform_x/impl.h" #endif /* or */ int foo (struct impl_t *data);
neither of these seems particularly appealing, , not style. while don't want swim upstream, don't want conflicting style when there might nicer way implement had in mind. think typedef solution on right track, , it's struct tag baggage i'm left with.
thoughts?
your current technique correct. trying utilize anonymous (untagged) struct
defeats you're trying — you'd have expose details of definition of struct
everywhere, means no longer have opaque info type.
in comment, user3629249 said:
the order of header file inclusions means there forwards reference struct generic.h
file; is, before struct defined, used. unlikely compile.
this observation wrong headers shown in question; accurate sample main()
code (which hadn't noticed until adding response).
the key point interface functions shown take or homecoming pointers type gen_t
, in turn maps struct impl_t
pointer. long client code not need allocate space structure, or dereference pointer construction access fellow member of structure, client code not need know details of structure. sufficient have construction type declared existing. utilize either of these declare existence of struct impl_t
:
struct impl_t; typedef struct impl_t gen_t;
the latter introduces alias gen_t
type struct impl_t
. see which part of c standard allows code compile? , does c standard consider there 1 or 2 struct uperms
entry types in header?
the original main()
programme in question was:
int main (int argc, char *argv[]) { int ret; gen_t data; ret = foo(&data); … }
this code cannot compiled gen_t
opaque (non-pointer) type. work ok with:
typedef struct impl_t *gen_t;
it not compile with:
typedef struct impl_t gen_t;
because compiler must know how big construction allocate right space data
, compiler cannot know size definition of opaque type is. (see is thought typedef
pointers? typedefing pointers structures.)
thus, main()
code should more like:
#include "generic.h" int main(int argc, char **argv) { gen_t *data = bar(argc, argv); int ret = foo(data); ... }
where (for example) bar()
defined extern gen_t *bar(int argc, char **argv);
, returns pointer opaque type gen_t
.
opinion split on whether improve utilize struct tagname
or utilize typedef
name. linux kernel 1 substantial body of code not utilize typedef
mechanism; structures explicitly struct tagname
. on other hand, c++ away need explicit typedef
; writing:
struct impl_t;
in c++ programme means name impl_t
name of type. since opaque construction types require tag (or end using void *
everything, bad whole legion of reasons, primary reason lose type safety using void *
; remember, typedef
introduces alias underlying type, not new distinct type), way code in c simulates c++:
typedef struct generic generic;
i avoid using _t
suffix on types because posix reserves _t
implementation use* (see what type followed _t
represent?). may lucky , away it. i've worked on code bases types dec_t
, loc_t
defined code base of operations (which not part of implementation — 'the implementation' means c compiler , supporting code, or c library , supporting code), , both types caused pain decades because of systems code ported defined types, system's prerogative. 1 of names managed rid of; other didn't. 'twas painful! if must utilize _t
(it convenient way indicate type), recommend using distinctive prefix too: pqr_typename_t
project pqr
, example.
* see bottom line of sec table in the name space in posix standard.
c portability
No comments:
Post a Comment