Tcl_Obj is the C structure that implements every Tcl value. The name is misleading. Tcl_Value would better describe its purpose, but that term was already taken by Tcl_CreateMathFunc() .
AMG: Tcl 9 renames Tcl_Obj to Tcl_Value [L1 ]. FM Tcl_Cache could be more explicit, since it caches the result of a previous parsing.
Tcl_Obj provides for both a string (UTF8) representation and an "internal" representation of the value, which is limited only by the constraints of the C language itself. Each Tcl_Obj carries information about the type of its internal representation, and how to perform a conversion from the string representation to the internal representation, and vice-versa. In this way, the string becomes the universal intermediate representation for conversions between types. To enhance performance, Tcl knows how to perform direct conversions between certain often-used types.
A Tcl_Obj is reference counted, and the allocator for it is very heavily tuned. It has a deeply unfortunate name, but the far more apt Tcl_Value was previously taken for handling user-defined expr functions - a now obsolete facility.
RS: thinks that the name is ok if one does not expect OO features, class membership etc. Objects have been there long before OO, and the name is certainly not under a monopoly (I'd object against that ;-). But the basic feature of Tcl_Obj's is that they have a string representation and possibly a problem-oriented one, but each can be regenerated from the other (also if you define your obj Obj types). If such type conversions occur frequently, this costs performance - the so-called shimmering occurs. E.g. see what happens to $i below:
for {set i 0} {$i<10} {incr i} { #here we need the integer rep puts [string length $i] ;#here the string rep.. puts [llength $i] ;# and here the list rep, so int rep goes away }
CMcC: I've put together a summary page of Tcl_Objs current for 8.4, containing information culled from the source.
A Tcl_Obj is defined as a structure containing:
Each Tcl_ObjType structure contains the following four function pointers plus a name.
DKF: You must not allocate a Tcl_Obj manually. Always call Tcl_NewObj (or one of its close relatives, such as Tcl_NewIntObj()) to do it for you. This is because Tcl uses a special memory management engine for them that is tuned to be extra efficient -- useful because Tcl uses these things a lot -- and that's only accessible through Tcl_NewObj (or some wholly internal APIs that aren't exposed outside the Tcl library).
AMG: In C extension code for Tcl you have several options with respect to reference counting:
There's no way Tcl can remotely zap your Tcl_Objs with nonpositive refcount unless you've passed your Tcl_Obj pointers to Tcl library functions. Tcl doesn't keep a list of Tcl_Objs in existence, so it can't sweep.
string length causes the internal cached interpretation of a value to be discarded :
% incr i 1 % ::tcl::unsupported::representation $i value is a int with a refcount of 2, object pointer at 0x6000660e0, internal representation 0x1:0x600066320, string representation "1" % string length $i 1 % ::tcl::unsupported::representation $i value is a string with a refcount of 2, object pointer at 0x6000660e0, internal representation 0x6000ad6a0:0x600066320, string representation "1"
Data members of Tcl_Obj, particularly internalRep, can be mutated, so a Tcl_Obj should be exclusively owned by one thread. See Thread safety in tclZipfs.c .
PYK 2018-05-12: Sometimes a Tcl_Obj is stored in the internal representation of another Tcl_Obj. This can lead to tricky issue such as this memory leak in foreach. The fix involved clearing the internal representation of the nested Tcl_Obj, but couldn't something else set the internal representation back to a problematic value again?