dwww Home | Manual pages | Find package

Tcl_Obj(3tcl)               Tcl Library Procedures               Tcl_Obj(3tcl)

______________________________________________________________________________

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 re-
                                     sult 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 cre-
       ate and copy values, and increment and decrement the  count  of  refer-
       ences  (pointers)  to  values.   The procedures are used in conjunction
       with ones that operate on specific types of values such as  Tcl_GetInt-
       FromObj  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  stor-
       ing 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  manipu-
       lated  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  instruc-
       tion 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  representa-
       tion 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 al-
       ways 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  re-
       claim 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 al-
       ways have a null byte after the last data byte, at offset length;  this
       allows string representations to be treated as conventional null-termi-
       nated 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 type-
       Ptr 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 num-
       ber, a pointer to a value containing additional information  needed  by
       the value's type to represent the value, a Tcl_WideInt integer, two ar-
       bitrary 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.   Main-
       taining  the  correct reference count is a key responsibility of exten-
       sion 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 re-
       fCount 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_New-
       StringObj respectively.  A value's string value is gotten with Tcl_Get-
       StringFromObj 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 com-
       puted 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_Get-
       String 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_GetBooleanFro-
       mObj 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 ele-
       ment 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 type-
       Ptr.   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  se-
       quence 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 in-
       ternal  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  deter-
       mine 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 refer-
       ence to the value is created.  The  macro  Tcl_DecrRefCount  decrements
       the count when a reference is no longer needed and, if the value's ref-
       erence count drops to zero, frees its storage.  A value shared by  dif-
       ferent code or data structures has refCount greater than 1.  Increment-
       ing 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 refer-
       ence 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 af-
       ter 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  lap-
       pend 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 lin-
       sert.  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  in-
       ternal  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_ListObjAppendEle-
       ment(3tcl), Tcl_ListObjIndex(3tcl), Tcl_ListObjReplace(3tcl),  Tcl_Reg-
       isterObjType(3tcl)

KEYWORDS
       internal  representation,  value, value creation, value type, reference
       counting, string representation, type conversion

Tcl                                   8.5                        Tcl_Obj(3tcl)

Generated by dwww version 1.14 on Thu Dec 19 13:25:10 CET 2024.