I am trying to link a Tcl variable to a C variable in order to pass the pointer to the latest during C thread creation and have a TCL-C thread shared variable (I don’t think I can use native TCL Thread Shared Variable functions).
I have some difficulties to link both variables.
Here is how I do:
#Tcl code, calling the C function:
set linkedVar 98
puts "linkedVar: $linkedVar"
load [file join [pwd] libCextension[info sharedlibextension]]
set threadId [createThreadC]
puts "Created thread n° $threadId"
puts "linkedVar: $linkedVar"
The createThreadC function creates a C thread, return its ID and tries to create a link with linkedVar.
// C function called by Tcl
static int
createThreadC_Cmd(
ClientData cdata,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
int linkedVar=2;
Tcl_LinkVar(interp, "linkedVar", (char *) &linkedVar, TCL_LINK_INT);
linkedVar=1;
...
# Thread creation, return Tcl object with thread ID
...
return TCL_OK;
}
Here is the output:
linkedVar: 98
Created thread n° -1227199680
linkedVar: 35
The linkedVar value changed, as C program had to, but it stores the wrong variable, should be 1 instead of 35.
Is it the (char *) &linkedVar cast which is wrong?
I was going to say the same stuff as Donal, but also wrote a demo. So here it is – basically your linked variable lifetime should match the interpreter lifetime.
Usage (building too using msvc 6):
This shows one way to clean things up by leveraging the command cleanup function.
You must be very careful if you use multiple threads and also have Tcl interpreters around. A Tcl interp is tied to the thread it was created on. So if you want the Shared structure to be passed among C threads you should loose the interp member. In that case I’d have this structure lifetime being handled by the application. Provided your Shared structure has a lifetime that is longer than any interpreter that has a command for which this is the clientData then everything will be ok and you don’t need to cleanup within the interpreter.