Tcl_NewObj(3tcl)
Tcl_Obj(3) Tcl Library Procedures Tcl_Obj(3)
_________________________________________________________________
NAME
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount,
Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep -
manipulate Tcl objects
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 an object; must have
been the result of a previous
call to Tcl_NewObj.
_________________________________________________________________
INTRODUCTION
This man page presents an overview of Tcl objects and how
they are used. It also describes generic procedures for
managing Tcl objects. These procedures are used to create
and copy objects, and increment and decrement the count of
references (pointers) to objects. The procedures are used
in conjunction with ones that operate on specific types of
objects such as Tcl_GetIntFromObj and
Tcl_ListObjAppendElement. The individual procedures are
described along with the data structures they manipulate.
Tcl's dual-ported objects provide a general-purpose mechan-
ism 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 objects behave like strings but
also hold an internal representation that can be manipulated
more efficiently. For example, a Tcl list is now
represented as an object that holds the list's string
representation as well as an array of pointers to the
Tcl Last change: 8.5 1
Tcl_Obj(3) Tcl Library Procedures Tcl_Obj(3)
objects for each list element. Dual-ported objects 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 objects
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 com-
puted when necessary, it is computed from the other
representation, and, once computed, it is saved. In addi-
tion, a change in one representation invalidates the other
one. As an example, a Tcl program doing integer calcula-
tions 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 objects contain an internal representa-
tion, their semantics are defined in terms of strings: an
up-to-date string can always be obtained, and any change to
the object will be reflected in that string when the
object'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.
Objects are allocated on the heap and are referenced using a
pointer to their Tcl_Obj structure. Objects are shared as
much as possible. This significantly reduces storage
requirements because some objects 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 pro-
cedure. 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 an object's storage.
Tcl objects are typed. An object'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 object is represented by a Tcl_Obj structure which
is defined as follows.
typedef struct Tcl_Obj {
int refCount;
char *bytes;
int length;
Tcl Last change: 8.5 2
Tcl_Obj(3) Tcl Library Procedures Tcl_Obj(3)
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 an object'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 an object's
string representation. If bytes is NULL, the string
representation is invalid.
An object'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 an object's internal
representation. This is either a (long) integer, a double-
precision floating-point number, a pointer to a value con-
taining additional information needed by the object's type
to represent the object, a Tcl_WideInt integer, two arbi-
trary 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
an object's storage. It holds the count of active refer-
ences to the object. Maintaining the correct reference
count is a key responsibility of extension writers. Refer-
ence counting is discussed below in the section STORAGE
MANAGEMENT OF OBJECTS.
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
Tcl Last change: 8.5 3
Tcl_Obj(3) Tcl Library Procedures Tcl_Obj(3)
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 objects is that they hold two
representations. An object typically starts out containing
only a string representation: it is untyped and has a NULL
typePtr. An object containing an empty string or a copy of
a specified string is created using Tcl_NewObj or
Tcl_NewStringObj respectively. An object's string value is
gotten with Tcl_GetStringFromObj or Tcl_GetString and
changed with Tcl_SetStringObj. If the object is later
passed to a procedure like Tcl_GetIntFromObj that requires a
specific internal representation, the procedure will create
one and set the object's typePtr. The internal representa-
tion is computed from the string representation. An
object's two representations are duals of each other:
changes made to one are reflected in the other. For exam-
ple, Tcl_ListObjReplace will modify an object'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 object types must check for invalid
representations and mark representations invalid when neces-
sary. The procedure Tcl_InvalidateStringRep is used to mark
an object's string representation invalid and to free any
storage associated with the old string representation.
Objects usually remain one type over their life, but occa-
sionally an object must be converted from one type to
another. For example, a C program might build up a string
in an object with repeated calls to Tcl_AppendToObj, and
then call Tcl_ListObjIndex to extract a list element from
the object. The same object holding the same string value
can have several different internal representations at dif-
ferent times. Extension writers can also force an object to
be converted from one type to another using the
Tcl_ConvertToType procedure. Only programmers that create
new object types need to be concerned about how this is
done. A procedure defined as part of the object type's
implementation creates a new internal representation for an
object and changes its typePtr. See the man page for
Tcl_RegisterObjType to see how to create a new object type.
Tcl Last change: 8.5 4
Tcl_Obj(3) Tcl Library Procedures Tcl_Obj(3)
EXAMPLE OF THE LIFETIME OF AN OBJECT
As an example of the lifetime of an object, consider the
following sequence of commands:
set x 123
This assigns to x an untyped object whose bytes member
points to 123 and length member contains 3. The object'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 object by
calling Tcl_GetIntFromObj. This procedure checks whether
the object is already an integer object. Since it is not,
it converts the object by setting the object's
internalRep.longValue member to the integer 123 and setting
the object's typePtr to point to the integer Tcl_ObjType
structure. Both representations are now valid. incr incre-
ments the object'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 object is needed and is
recomputed. The string representation is now 124 and both
representations are again valid.
STORAGE MANAGEMENT OF OBJECTS
Tcl objects are allocated on the heap and are shared as much
as possible to reduce storage requirements. Reference
counting is used to determine when an object is no longer
needed and can safely be freed. An object 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 object is created. The macro
Tcl_DecrRefCount decrements the count when a reference is no
longer needed and, if the object's reference count drops to
zero, frees its storage. An object shared by different code
or data structures has refCount greater than 1. Increment-
ing an object'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
objects between calling and called Tcl procedures to avoid
having to copy objects. It assigns the call's argument
objects to the procedure's formal parameter variables. In
doing so, it calls Tcl_IncrRefCount to increment the refer-
ence count of each argument since there is now a new refer-
ence to it from the formal parameter. When the called pro-
cedure returns, the interpreter calls Tcl_DecrRefCount to
decrement each argument's reference count. When an object's
reference count drops less than or equal to zero,
Tcl Last change: 8.5 5
Tcl_Obj(3) Tcl Library Procedures Tcl_Obj(3)
Tcl_DecrRefCount reclaims its storage. Most command pro-
cedures do not have to be concerned about reference counting
since they use an object's value immediately and do not
retain a pointer to the object after they return. However,
if they do retain a pointer to an object in a data struc-
ture, they must be careful to increment its reference count
since the retained pointer is a new reference.
Command procedures that directly modify objects such as
those for lappend and linsert must be careful to copy a
shared object before changing it. They must first check
whether the object is shared by calling Tcl_IsShared. If
the object is shared they must copy the object by using
Tcl_DuplicateObj; this returns a new duplicate of the origi-
nal object that has refCount 0. If the object is not
shared, the command procedure "owns" the object and can
safely modify it directly. For example, the following code
appears in the command procedure that implements linsert.
This procedure modifies the list object 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 object is shared before incrementing
the integer in its internal representation. If it is
shared, it needs to duplicate the object in order to avoid
accidentally changing values in other data structures.
SEE ALSO
Tcl_ConvertToType(3), Tcl_GetIntFromObj(3),
Tcl_ListObjAppendElement(3), Tcl_ListObjIndex(3),
Tcl_ListObjReplace(3), Tcl_RegisterObjType(3)
KEYWORDS
internal representation, object, object creation, object
type, reference counting, string representation, type
conversion
Tcl Last change: 8.5 6
Man(1) output converted with
man2html