1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
[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]
|