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