Tcl_Obj(3)

Tcl_Obj(3)

ntohs Home Page Subroutines Index ObjectType


_________________________________________________________________

NAME
       Tcl_NewObj,  Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_Decr-
       RefCount, Tcl_IsShared - 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_ListObjAppen-
       dElement.  The individual procedures are  described  along
       with the data structures they manipulate.

       Tcl's dual-ported objects provide a general-purpose mecha-
       nism 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  manipu-
       lated  more  efficiently.   For example, a Tcl list is now
       represented as an object that holds the list's string rep-
       resentation 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 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  con-
       stantly  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 repre-
       sentation 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_Get-
       StringFromObj.

       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  argu-
       ments,  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 representa-
       tion is controlled by its type.  Seven  types  are  prede-
       fined 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 representa-
       tion.  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-ter-
       minated 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 rep-
       resentation is invalid.

       The  internalRep  union  member holds an object's internal
       representation.  This is either a (long) integer,  a  dou-
       ble-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 refer-
       ence count is a key responsibility of  extension  writers.
       Reference counting is discussed below in the section STOR-
       AGE 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 repre-
       sentations.  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_ListOb-
       jReplace  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  con-
       cerned  with  how  this  is done and simply use procedures
       such as Tcl_GetBooleanFromObj or  Tcl_ListObjIndex.   Pro-
       grammers  that implement their own object types must check
       for  invalid  representations  and  mark   representations
       invalid  when  necessary.   The  procedure  Tcl_Invalidat-
       eStringRep is used to mark an object's string  representa-
       tion  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_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  internal-
       Rep.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.   Refer-
       ence  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  ref-
       erence  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_Decr-
       RefCount to decrement  each  argument's  reference  count.
       When  an object's reference count drops to zero, Tcl_Decr-
       RefCount 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 lin-
       sert.  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 increment-
       ing 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_ListObjAppen-
       dElement, Tcl_ListObjIndex, Tcl_ListObjReplace, Tcl_Regis-
       terObjType

KEYWORDS
       internal representation, object, object  creation,  object
       type, reference counting, string representation, type con-
       version

ntohs Home Page Subroutines Index ObjectType