[comment {-*- mode: tcl ; fill-column: 90 -*-}]

When the set of predefined argument types is not enough the oldest way of handling the
situation is falling back to the structures used by Tcl to manage values, i.e.
[type Tcl_Obj*].

[list_begin enumerated]

[enum][vset base][example {
    critcl::cproc hello {object x} void {
	/* Tcl_Obj* x */
	int len;
	char* str = Tcl_GetStringFromObj (x, &len);
	printf("hello world, from %s (%d bytes)\n", str, len);
    }
}][vset rebuild]

[enum] Having direct access to the raw [type Tcl_Obj*] value all functions of the public
Tcl API for working with Tcl values become usable. The downside of that is that all the
considerations for handling them apply as well.

[para] In other words, the C code becomes responsible for handling the reference counts
correctly, for duplicating shared [type Tcl_Obj*] structures before modifying them, etc.

[para] One thing the C code is allowed to do without restriction is to [term shimmer] the
internal representation of the value as needed, through the associated Tcl API
functions. For example [fun Tcl_GetWideIntFromObj] and the like.

It actually has to be allowed to do so, as the type checking done as part of such
conversions is now the responsibility of the C code as well.

[para] For the predefined types this is all hidden in the translation layer generated by
[vset critcl].

[para] If more than one command has to perform the same kind of checking and/or conversion
it is recommended to move the core of the code into proper C functions for proper sharing
among the commands.

[enum] This is best done by defining a custom argument type using [vset critcl] commands.

This extends the translation layer [vset critcl] is able to generate.

The necessary conversions, type checks, etc. are then again hidden from the bulk of the
application C code.

[para] We will come back to this.

[list_end]
