I am working to update old software (written to build against Tcl/Tk 8.3) so that it builds against more modern distributions. I am taking this as an opportunity to learn about C and Tcl, both of which I had never programmed in when this project began. So, I'm very novice.
One of the most confusing things for me in learning about the Tcl API is ClientData
. Many functions in the API take it as an argument, but the C extension almost never uses it. I got the impression from this answer that the global definition is rarely used:
The whole-extension ClientData is intended for extensions that want to publish their own stub table ... that other extensions can build against. This is a very rare thing to want to do; leave at NULL if you don't want it.
So it seems that it is basically a void
parameter that you then need to type cast or handle internally. But there are some places in the code where I need to interact with ClientData (e.g. for Idle Processes, as in the following):
typedef struct graph *Graph;
struct graph {
int num;
int hidden;
int needsRedraw;
...
};
flag drawNow(ClientData data) {
Graph G;
int g = (int) data;
if (!(G = lookupGraph(g))) return TCL_OK;
return drawGraph(G);
}
flag drawLater(Graph G) {
if (!G->needsRedraw && !G->hidden) {
G->needsRedraw = TRUE;
Tcl_DoWhenIdle((Tcl_IdleProc *) drawNow, (ClientData) G->num);
}
return TCL_OK;
}
The cast to integer results in the following warning when I compile:
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
My main confusion is (ClientData) G->num
---I don't understand what I am casting to, because I don't know what kind of a thing ClientData is. If I look in the Tcl sources, I do not find clarity:
tclCompile.h:220:typedef ClientData (AuxDataDupProc) (ClientData clientData);
tclInt.h:2520:typedef ClientData (TclFSGetCwdProc2)(ClientData clientData);
tclOOInt.h:73:typedef ClientData (TclOO_PmCDCloneProc)(ClientData clientData);
A couple of final points: These compiler warnings existed before I started doing any updates to the code. The program appears to work on the old systems where the original code does compile and run. So, I am not sure if this warning amounts to anything... but it spooks me, and as long as I am spending time with the code and learning about C and Tcl, I was hoping to get to the bottom of it.
Apologies in advance if I did not provide enough relevant information. I'm happy to provide more, but this my current best effort at a good question.
In general, ClientData
means “pointer that Tcl promises it won't interpret for you”, and is virtually always something that will get handed back to you in a callback. Treat it like void *
(which is what it is a typedef
for).
The answer you refer to is talking specifically about the Tcl_PkgRequireEx
function, where the ClientData
stuff is used for passing around references to stub tables. You can use this to pass your own, but it's quite involved. It's a pretty rare thing though; most people never touch on those mysteries.
In general, it's more common to see it used in relation to Tcl_CreateCommand
or Tcl_CreateObjCommand
. There, the clientData
parameter is a pointer that will get passed back to the implementation callback when the created command is called; this is great for commands that represent instances of classes and things like that. Tcl uses this for things like procedures; the proc
command uses the clientData
to pass a pointer to a structure describing the body script (and other stuff) to the C function that implements procedures. If you know a little bit about Tk, clientData
is used extensively there to pass the low-level handle to the window structure.
With Tcl_DoWhenIdle
, it's again a pointer being handed over to the callback. Different signature of callback function, of course, but same basic underlying idea.
If Tcl provided C++ APIs, it would probably do things a bit differently since it's possible to talk about pointers to an instance method in that language. But Tcl's API is a C API, so everything has to work like this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With