Provided by: tcl8.6-doc_8.6.14+dfsg-1build1_all 

NAME
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep -
manipulate Tcl values
SYNOPSIS
#include <tcl.h>
Tcl_Obj *
Tcl_NewObj()
Tcl_Obj *
Tcl_DuplicateObj(objPtr)
Tcl_IncrRefCount(objPtr)
Tcl_DecrRefCount(objPtr)
int
Tcl_IsShared(objPtr)
Tcl_InvalidateStringRep(objPtr)
ARGUMENTS
Tcl_Obj *objPtr (in) Points to a value; must have been the result of a previous call to
Tcl_NewObj.
________________________________________________________________________________________________________________
INTRODUCTION
This man page presents an overview of Tcl values (called Tcl_Objs for historical reasons) and how they
are used. It also describes generic procedures for managing Tcl values. These procedures are used to
create and copy values, and increment and decrement the count of references (pointers) to values. The
procedures are used in conjunction with ones that operate on specific types of values such as
Tcl_GetIntFromObj and Tcl_ListObjAppendElement. The individual procedures are described along with the
data structures they manipulate.
Tcl's dual-ported values provide a general-purpose mechanism for storing and exchanging Tcl values. They
largely replace the use of strings in Tcl. For example, they are used to store variable values, command
arguments, command results, and scripts. Tcl values behave like strings but also hold an internal
representation that can be manipulated more efficiently. For example, a Tcl list is now represented as a
value that holds the list's string representation as well as an array of pointers to the values for each
list element. Dual-ported values avoid most runtime type conversions. They also improve the speed of
many operations since an appropriate representation is immediately available. The compiler itself uses
Tcl values to cache the instruction bytecodes resulting from compiling scripts.
The two representations are a cache of each other and are computed lazily. That is, each representation
is only computed when necessary, it is computed from the other representation, and, once computed, it is
saved. In addition, a change in one representation invalidates the other one. As an example, a Tcl
program doing integer calculations can operate directly on a variable's internal machine integer
representation without having to constantly convert between integers and strings. Only when it needs a
string representing the variable's value, say to print it, will the program regenerate the string
representation from the integer. Although values contain an internal representation, their semantics are
defined in terms of strings: an up-to-date string can always be obtained, and any change to the value
will be reflected in that string when the value's string representation is fetched. Because of this
representation invalidation and regeneration, it is dangerous for extension writers to access Tcl_Obj
fields directly. It is better to access Tcl_Obj information using procedures like Tcl_GetStringFromObj
and Tcl_GetString.
Values are allocated on the heap and are referenced using a pointer to their Tcl_Obj structure. Values
are shared as much as possible. This significantly reduces storage requirements because some values such
as long lists are very large. Also, most Tcl values are only read and never modified. This is
especially true for procedure arguments, which can be shared between the caller and the called procedure.
Assignment and argument binding is done by simply assigning a pointer to the value. Reference counting
is used to determine when it is safe to reclaim a value's storage.
Tcl values are typed. A value's internal representation is controlled by its type. Several types are
predefined in the Tcl core including integer, double, list, and bytecode. Extension writers can extend
the set of types by defining their own Tcl_ObjType structs.
THE TCL_OBJ STRUCTURE
Each Tcl value is represented by a Tcl_Obj structure which is defined as follows.
typedef struct Tcl_Obj {
int refCount;
char *bytes;
int length;
const Tcl_ObjType *typePtr;
union {
long longValue;
double doubleValue;
void *otherValuePtr;
Tcl_WideInt wideValue;
struct {
void *ptr1;
void *ptr2;
} twoPtrValue;
struct {
void *ptr;
unsigned long value;
} ptrAndLongRep;
} internalRep;
} Tcl_Obj;
The bytes and the length members together hold a value's UTF-8 string representation, which is a counted
string not containing null bytes (UTF-8 null characters should be encoded as a two byte sequence: 192,
128.) bytes points to the first byte of the string representation. The length member gives the number
of bytes. The byte array must always have a null byte after the last data byte, at offset length; this
allows string representations to be treated as conventional null-terminated C strings. C programs use
Tcl_GetStringFromObj and Tcl_GetString to get a value's string representation. If bytes is NULL, the
string representation is invalid.
A value's type manages its internal representation. The member typePtr points to the Tcl_ObjType
structure that describes the type. If typePtr is NULL, the internal representation is invalid.
The internalRep union member holds a value's internal representation. This is either a (long) integer, a
double-precision floating-point number, a pointer to a value containing additional information needed by
the value's type to represent the value, a Tcl_WideInt integer, two arbitrary pointers, or a pair made up
of an unsigned long integer and a pointer.
The refCount member is used to tell when it is safe to free a value's storage. It holds the count of
active references to the value. Maintaining the correct reference count is a key responsibility of
extension writers. Reference counting is discussed below in the section STORAGE MANAGEMENT OF VALUES.
Although extension writers can directly access the members of a Tcl_Obj structure, it is much better to
use the appropriate procedures and macros. For example, extension writers should never read or update
refCount directly; they should use macros such as Tcl_IncrRefCount and Tcl_IsShared instead.
A key property of Tcl values is that they hold two representations. A value typically starts out
containing only a string representation: it is untyped and has a NULL typePtr. A value containing an
empty string or a copy of a specified string is created using Tcl_NewObj or Tcl_NewStringObj
respectively. A value's string value is gotten with Tcl_GetStringFromObj or Tcl_GetString and changed
with Tcl_SetStringObj. If the value is later passed to a procedure like Tcl_GetIntFromObj that requires
a specific internal representation, the procedure will create one and set the value's typePtr. The
internal representation is computed from the string representation. A value's two representations are
duals of each other: changes made to one are reflected in the other. For example, Tcl_ListObjReplace
will modify a value's internal representation and the next call to Tcl_GetStringFromObj or Tcl_GetString
will reflect that change.
Representations are recomputed lazily for efficiency. A change to one representation made by a procedure
such as Tcl_ListObjReplace is not reflected immediately in the other representation. Instead, the other
representation is marked invalid so that it is only regenerated if it is needed later. Most C
programmers never have to be concerned with how this is done and simply use procedures such as
Tcl_GetBooleanFromObj or Tcl_ListObjIndex. Programmers that implement their own value types must check
for invalid representations and mark representations invalid when necessary. The procedure
Tcl_InvalidateStringRep is used to mark a value's string representation invalid and to free any storage
associated with the old string representation.
Values usually remain one type over their life, but occasionally a value must be converted from one type
to another. For example, a C program might build up a string in a value with repeated calls to
Tcl_AppendToObj, and then call Tcl_ListObjIndex to extract a list element from the value. The same value
holding the same string value can have several different internal representations at different times.
Extension writers can also force a value to be converted from one type to another using the
Tcl_ConvertToType procedure. Only programmers that create new value types need to be concerned about how
this is done. A procedure defined as part of the value type's implementation creates a new internal
representation for a value and changes its typePtr. See the man page for Tcl_RegisterObjType to see how
to create a new value type.
EXAMPLE OF THE LIFETIME OF A VALUE
As an example of the lifetime of a value, consider the following sequence of commands:
set x 123
This assigns to x an untyped value whose bytes member points to 123 and length member contains 3. The
value's typePtr member is NULL.
puts "x is $x"
x's string representation is valid (since bytes is non-NULL) and is fetched for the command.
incr x
The incr command first gets an integer from x's value by calling Tcl_GetIntFromObj. This procedure
checks whether the value is already an integer value. Since it is not, it converts the value by setting
the value's internal representation to the integer 123 and setting the value's typePtr to point to the
integer Tcl_ObjType structure. Both representations are now valid. incr increments the value's integer
internal representation then invalidates its string representation (by calling Tcl_InvalidateStringRep)
since the string representation no longer corresponds to the internal representation.
puts "x is now $x"
The string representation of x's value is needed and is recomputed. The string representation is now 124
and both representations are again valid.
STORAGE MANAGEMENT OF VALUES
Tcl values are allocated on the heap and are shared as much as possible to reduce storage requirements.
Reference counting is used to determine when a value is no longer needed and can safely be freed. A
value just created by Tcl_NewObj or Tcl_NewStringObj has refCount 0. The macro Tcl_IncrRefCount
increments the reference count when a new reference to the value is created. The macro Tcl_DecrRefCount
decrements the count when a reference is no longer needed and, if the value's reference count drops to
zero, frees its storage. A value shared by different code or data structures has refCount greater than
1. Incrementing a value's reference count ensures that it will not be freed too early or have its value
change accidentally.
As an example, the bytecode interpreter shares argument values between calling and called Tcl procedures
to avoid having to copy values. It assigns the call's argument values to the procedure's formal
parameter variables. In doing so, it calls Tcl_IncrRefCount to increment the reference count of each
argument since there is now a new reference to it from the formal parameter. When the called procedure
returns, the interpreter calls Tcl_DecrRefCount to decrement each argument's reference count. When a
value's reference count drops less than or equal to zero, Tcl_DecrRefCount reclaims its storage. Most
command procedures do not have to be concerned about reference counting since they use a value's value
immediately and do not retain a pointer to the value after they return. However, if they do retain a
pointer to a value in a data structure, they must be careful to increment its reference count since the
retained pointer is a new reference.
Command procedures that directly modify values such as those for lappend and linsert must be careful to
copy a shared value before changing it. They must first check whether the value is shared by calling
Tcl_IsShared. If the value is shared they must copy the value by using Tcl_DuplicateObj; this returns a
new duplicate of the original value that has refCount 0. If the value is not shared, the command
procedure “owns” the value and can safely modify it directly. For example, the following code appears in
the command procedure that implements linsert. This procedure modifies the list value passed to it in
objv[1] by inserting objc-3 new elements before index.
listPtr = objv[1];
if (Tcl_IsShared(listPtr)) {
listPtr = Tcl_DuplicateObj(listPtr);
}
result = Tcl_ListObjReplace(interp, listPtr, index, 0,
(objc-3), &(objv[3]));
As another example, incr's command procedure must check whether the variable's value is shared before
incrementing the integer in its internal representation. If it is shared, it needs to duplicate the
value in order to avoid accidentally changing values in other data structures.
SEE ALSO
Tcl_ConvertToType(3tcl), Tcl_GetIntFromObj(3tcl), Tcl_ListObjAppendElement(3tcl), Tcl_ListObjIndex(3tcl),
Tcl_ListObjReplace(3tcl), Tcl_RegisterObjType(3tcl)
KEYWORDS
internal representation, value, value creation, value type, reference counting, string representation,
type conversion
Tcl 8.5 Tcl_Obj(3tcl)