A dilemma with handles
Richard A. O'Keefe
ok at goanna.cs.rmit.oz.au
Wed Oct 3 11:41:33 AEST 1990
In article <markd.654876849 at sunchat>, markd at iti.org (Mark Delany) writes:
> Now my question relates to the definition of "handle". Within the
> library this is simply a pointer to a structure that holds all the
> goodies necessary to achieve the results.
Remember that C allows you to use "incomplete types". You can have
a header file
/* pubstuff.h */
typedef struct BlackMystery *handle;
extern handle zzopen(char *title, char *mode);
...
/* end of pubstuff.h */
which your users can get at, and a header file
/* realstuff.h */
#include "pubstuff.h"
struct BlackMystery
{
/* system-dependent stuff spelled out here */
};
/* other declarations */
/* end of realstuff.h */
and then the file in which you implement, say, zzopen can
#include "realstuff.h"
When a user program #includes "pubstuff.h" they get handles which are
pointers to an incomplete type. However, the C compiler will know
everything that it needs to manage these pointers, because "all struct
pointers smell the same". There are some big advantages to doing it
this way.
- you don't have to tell any lies; just conceal some of the truth
- you don't need any casts
- Lint remains your friend:
When you Lint user code against your library there won't have
been any casts needed, so you _will_ benefit from type checking
- user code will be unable to declare variables of type
struct BlackMystery, and it will be unable to deference handles.
For example, given
handle p, q;
the assignment
p = q;
will be allowed and will work correctly, but
*p = *q;
will be disallowed and rejected at compile time.
This approach isn't a _dummy_ declaration, just an _incomplete_ one.
--
Fixed in the next release.
More information about the Comp.lang.c
mailing list