Provided by: tcl8.5-doc_8.5.19-1_all bug

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 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 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 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.  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_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 containing additional information needed
       by the object's type to represent the object, 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 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 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 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   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  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_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 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 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 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 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 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 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 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, object, object creation, object type, reference counting, string representation,
       type conversion

Tcl                                                    8.5                                         Tcl_Obj(3tcl)