Tcl_Obj (3)
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
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 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 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 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 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 objects 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 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.
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 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 an object's storage.
Tcl objects are typed.
An object's internal representation is controlled by its type.
Seven types are predefined in the Tcl core
including integer, double, list, and bytecode.
Extension writers can extend the set of types
by using the procedure Tcl_RegisterObjType .
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_ObjType *typePtr;
union {
long longValue;
double doubleValue;
VOID *otherValuePtr;
struct {
VOID *ptr1;
VOID *ptr2;
} twoPtrValue;
} internalRep;
} Tcl_Obj;
The bytes and the length members together hold
an object's string representation,
which is a counted or binary string
that may contain binary data with embedded null bytes.
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 after the last byte,
at offset length;
this allows string representations that do not contain nulls
to be treated as conventional null-terminated C strings.
C programs use Tcl_GetStringFromObj 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 containing additional information
needed by the object's type to represent the object,
or two arbitrary pointers.
The refCount member is used to tell when it is safe to free
an object's storage.
It holds the count of active references to the object.
Maintaining the correct reference count is a key responsibility
of extension writers.
Reference 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 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
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 representation 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 example, Tcl_ListObjReplace will modify an object's
internal representation and the next call to Tcl_GetStringFromObj
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 necessary.
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 occasionally 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_StringObjAppend,
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 different 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.
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 increments 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.
Incrementing an object's reference count ensures that
it won't be freed too early or have its value change accidently.
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 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 an object's reference count drops to zero,
Tcl_DecrRefCount reclaims its storage.
Most command procedures do not have to be concerned about
reference counting since they use an object's value immediately
and don't retain a pointer to the object after they return.
However, if they do retain a pointer to an object 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 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 original 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 accidently changing values in other data structures.
SEE ALSO
Tcl_ConvertToType Tcl_GetIntFromObj Tcl_ListObjAppendElement Tcl_ListObjIndex Tcl_ListObjReplace Tcl_RegisterObjType
KEYWORDS
internal representation, object, object creation, object type, reference counting, string representation, type conversion
'\"
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: StringObj.3,v 1.2 1998/09/14 18:39:50 stanton Exp $
'\"
'\" The definitions below are for supplemental macros used in Tcl/Tk
'\" manual entries.
'\"
'\" .AP type name in/out ?indent?
'\" Start paragraph describing an argument to a library procedure.
'\" type is type of argument (int, etc.), in/out is either "in", "out",
'\" or "in/out" to describe whether procedure reads or modifies arg,
'\" and indent is equivalent to second arg of .IP (shouldn't ever be
'\" needed; use .AS below instead)
'\"
'\" .AS ?type? ?name?
'\" Give maximum sizes of arguments for setting tab stops. Type and
'\" name are examples of largest possible arguments that will be passed
'\" to .AP later. If args are omitted, default tab stops are used.
'\"
'\" .BS
'\" Start box enclosure. From here until next .BE, everything will be
'\" enclosed in one large box.
'\"
'\" .BE
'\" End of box enclosure.
'\"
'\" .CS
'\" Begin code excerpt.
'\"
'\" .CE
'\" End code excerpt.
'\"
'\" .VS ?version? ?br?
'\" Begin vertical sidebar, for use in marking newly-changed parts
'\" of man pages. The first argument is ignored and used for recording
'\" the version when the .VS was added, so that the sidebars can be
'\" found and removed when they reach a certain age. If another argument
'\" is present, then a line break is forced before starting the sidebar.
'\"
'\" .VE
'\" End of vertical sidebar.
'\"
'\" .DS
'\" Begin an indented unfilled display.
'\"
'\" .DE
'\" End of indented unfilled display.
'\"
'\" .SO
'\" Start of list of standard options for a Tk widget. The
'\" options follow on successive lines, in four columns separated
'\" by tabs.
'\"
'\" .SE
'\" End of list of standard options for a Tk widget.
'\"
'\" .OP cmdName dbName dbClass
'\" Start of description of a specific option. cmdName gives the
'\" option's name as specified in the class command, dbName gives
'\" the option's name in the option database, and dbClass gives
'\" the option's class in the option database.
'\"
'\" .UL arg1 arg2
'\" Print arg1 underlined, then print arg2 normally.
'\"
'\" RCS: @(#) $Id: man.macros,v 1.2 1998/09/14 18:39:54 stanton Exp $
'\"
'\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
t .wh -1.3i ^B
^l \n(.l
b
'\" # Start an argument description
AP
!"\\$4"" .TP \\$4
\{\
!"\\$2"" .TP \\n()Cu
.TP 15
|