"Module":"typesafe_cb",
"Title":"typesafe_cb - macros for safe callbacks.",
"Author":"dinesh",
"Dependencies":[
]
"Description":[
{
"str":""
},
{
"str":"The basis of the typesafe_cb header is cast_if_type(): a"
},
{
"str":"conditional cast macro.   If an expression exactly matches a given"
},
{
"str":"type, it is cast to the target type, otherwise it is left alone."
},
{
"str":""
},
{
"str":"This allows us to create functions which take a small number of"
},
{
"str":"specific types, rather than being forced to use a void *.  In"
},
{
"str":"particular, it is useful for creating typesafe callbacks as the"
},
{
"str":"helpers typesafe_cb(), typesafe_cb_preargs() and"
},
{
"str":"typesafe_cb_postargs() demonstrate."
},
{
"str":""
},
{
"str":"The standard way of passing arguments to callback functions in C is"
},
{
"str":"to use a void pointer, which the callback then casts back to the"
},
{
"str":"expected type.  This unfortunately subverts the type checking the"
},
{
"str":"compiler would perform if it were a direct call.  Here's an example:"
},
{
"str":""
},
{
"str":"	static void my_callback(void *_obj)"
},
{
"str":"	{"
},
{
"str":"		struct obj *obj = _obj;"
},
{
"str":"		..."
},
{
"str":"	}"
},
{
"str":"	..."
},
{
"str":"		register_callback(my_callback, &my_obj);"
},
{
"str":""
},
{
"str":"If we wanted to use the natural type for my_callback (ie. "void"
},
{
"str":"my_callback(struct obj *obj)"), we could make register_callback()"
},
{
"str":"take a void * as its first argument, but this would subvert all"
},
{
"str":"type checking.  We really want register_callback() to accept only"
},
{
"str":"the exactly correct function type to match the argument, or a"
},
{
"str":"function which takes a void *."
},
{
"str":""
},
{
"str":"This is where typesafe_cb() comes in: it uses cast_if_type() to"
},
{
"str":"cast the callback function if it matches the argument type:"
},
{
"str":""
},
{
"str":"	void _register_callback(void (*cb)(void *arg), void *arg);"
},
{
"str":"	#define register_callback(cb, arg)				\"
},
{
"str":"		_register_callback(typesafe_cb(void, (cb), (arg)), (arg))"
},
{
"str":""
},
{
"str":"On compilers which don't support the extensions required"
},
{
"str":"cast_if_type() and friend become an unconditional cast, so your"
},
{
"str":"code will compile but you won't get type checking."
},
]
