vcanim.gif (8357 bytes)Arrays in Softwish
Home ] Sales ] Products ] Services ] Support ] Downloads ]

 

 


Arrays

Native Tcl arrays do not represent contiguous blocks of memory as C arrays do. Therefore SoftWish does not pass Tcl arrays as parameters to SAA calls which require arrays. Instead SoftWish provides its own allocation procedures. Since there may be a difference in the size of different C types which have identical string representations (such as long and int), SoftWish provides separate allocation routines for each type. SAA_AllocInteger allocates integers, SAA_AllocFloat allocates floats and SAA_AllocDouble allocates doubles. All these allocation procedures return a procedure for accessing the allocated entities. SoftWish treats strings as a special case and will generate any arrays needed itself, so one does not normally need to use SAA_AllocChar. Alloc calls take an optional size argument, so:

set myFloatArray [ SAA_AllocFloat 25 ]

allocates an array of 25 floats, in a single contiguous chunk of memory (a C array). myFloatArray is a Tcl variable. The access procedure is used to get and set elements of an array. The access procedure can take 2 or 3 arguments. Here are some examples:

access $myFloatArray 3 27.9

sets the value of the 4th element of the array,  myFloatArray, to 27.9. Because the arrays are 0 based (just like C arrays) using the index 3 gets you the 4th element.

set temp [access $myFloatArray 3]

sets temp to 27.9, the value of the 4th element of the array.

set totalElements [access $myFloatArray -size]

sets totalElements to 25, the number of elements in myFloatArray.

 

One frees allocated data of any type using SAA_Free. So, to free the array of floats allocated and accessed above, one would:

   SAA_free $myFloatArray

 

SWU provides routines for easily converting between the C-style arrays returned by the Alloc functions and TCL arrays and lists .

Arrays of strings are passed as the name of a list consisting of the strings. So to pass the three strings "tom", "dick" and "harry" one would :

set myStrings [list "tom" "disk" "harry" ] }

and then pass myStrings to any function which requires an array of 3 strings. The string NULL is a reserved string, which is used when you wish to specify an empty string. Thus NULL is the same as "". This means that you cannot use NULL as the name of a variable and expect SAA calls to understand it.

Arrays of strings are returned from a function into a list of strings, each string of which must be large enough to contain the returned data. This means that a call to

set returnedStrings [list "one" "two" ]
SAA_dummyReturnStringsFunction $returnedStrings

would be capable of receiving a pair of 3 character strings back from SAA_dummyReturnStringsFunction. The list named returnedStrings would then no longer contain "one" and "two", but 2 new 3 character strings. SAA calls which return strings usually have a pair of helper functions, the first of which tells the number of strings which will be returned, and the second of which tells the size of each such string by generating an array of integers (each element of which gives the necessary size of the corresponding string). SWU_emptyStringList takes such an array and returns a list with one string per array element which has the number of characters specified by the array element. So to call the above dummy SAA function safely one would:

SAA_dummyNbReturnStringsHelperFunction numberOfReturnStrings
set returnStringSizes [SAA_AllocInt $numberOfReturnStrings]
SAA_dummyReturnStringsHelperFunction $numberOfReturnStrings $returnedStringSizes
set returnedStrings [SWU_emptyStringList $returnedStringSizes 1]
SAA_dummyReturnStringsFunction $returnedStrings

SWU_emptyStringList can also be passed a Tcl list of integers, or a single integer. So

set myStrings [SWU_emptyStringList { 3 3 7} ]

will build an array of strings the first and second strings of which have 3 characters and the third string of which has 7 characters.

set myStrings [SWU_emptyStringList 15 ]

will build a single string 15 characters long.

SAA_AllocChar allocates an array of bytes. It should be used when one wants to pass an array of 8 bit numbers, otherwise it is almost always easier to use strings.

Allocating a Tcl analog of a C language pointer to an unknown type is done by SAA_AllocVoidStar, like this:

set cusvals [ SAA_AllocVoidStar ]

Now cusvals can be passed to any SAA_function which takes a parameter of type void *, for example:

# CustomContext1 gets set by SoftWish
SAA_customContextGetCustomValueList customContext1 $cusvals

You can allocate an array of such pointers by specifying a second parameter.

set myPointers [SAA_AllocVoidStar 10]

returns an array of 10 pointers.

set myPointer [SAA_AllocVoidStar]
access $myPointer -alloc 12

creates a pointer to an unknown type, allocates an array of 12 bytes and sets myPointer to point to this 12 bytes array.

SAA_free $myPointer
 
would free the pointer we just allocated. Note that it would NOT free the array of 12 bytes from the pointer that was allocated by: access $myPointer -alloc 12. That data would be freed by:
access $myPointer -alloc 0
so to free the pointer and the data pointed to, one would first free the data pointed to, like this
access $myPointer -alloc 0
and then free the pointer itself, like this:
    SAA_free $myPointer

Here is another example:

      set $myPointer [SAA_AllocVoidStar]

    access $myPointer "woof woof"

does the same thing except that it also sets the beginning of the 12 bytes to be the string "woof woof".

access $myPointer -string

returns what myPointer is pointing at as a string. Thus

set myPointer [SAA_AllocVoidStar]
access $myPointer "woof woof"
access $myPointer -string

returns "woof woof".

set myPointer [SAA_AllocVoidStar]
access $myPointer -- "woof woof"

is the safest way to allocate and set an array, since this prevents any confusion between the initializing string and switches such as -string and -alloc. We would free the array containing "woof woof" like this:

SAA_free $myPointer
after that we would free the pointer that was pointing to the array like this:
alloc $myPointer -alloc 0
 

One allocates a scalar object using the same procedure call which allocates an array of such objects with no parameters, so :

set a [ SAA_AllocLong ]

allocates and returns a single longword.. This is different from:

set b [ SAA_AllocLong 1 ]

which allocates and returns an array containing a single longword. The difference between scalars and arrays is that to set an array an index and a value MUST be provided, while to set a scalar ONLY the value is provided. For example:

access $b 0 10
access $a 20

sets the first (and only) element of the array b to 10. The second sets the scalar longword accessed by a to 20. Note that

access $b 0
access $a

returns the value of the first element of the array  b and the scalar accessed by a, respectively. So

access $b 0 45.0

sets the first element of array b to 45.0, while

access $a 0 45.0

sets the scalar accessed by a to 45.0


One can get the number of elements in an array by passing the access procedure the array followed by the keyword "-size", so:

access $b -size

returns 1 since the array accessed by b has 1 element.

access $a -size

returns "scalar". This gives one an easy way to distinguish between arrays of 1 element and scalars.


One can make a copy of an entire array or an element of an array by passing the access procedure the array followed by the keyword -clone. Suppose we had an array of 25 booleans, allocated like this:

set myBooleans [SAA_AllocBoolean 25]

To duplicate this array we would:

set copyBoolean [access $myBooleans -clone]

This creates a duplicate array of 25 Booleans, such that:

[$copyBooleans $i ]

is equal to

[$myBooleans $i]

for i=0,1,...24.  Changing an element of myBooleans does not change the corresponding element of  copy Boolean. This is not what happens if one makes a copy without using access and -clone.

    set myOtherFloatArray $myFloatArray

creates another name for the myFloatArray. It does not allocate a second array. This means that changing an element of myFloatArray changes the corresponding element of myOtherFloatArray since these are different names for the same elements (pointer to the same memory).

To make a copy of the 8th element of the above array we would:

set copyBoolean7 [$myBooleans 7 -clone]

this makes copyBoolean7 the name of an accessor function for a new boolean, which is a duplicate of [$myBooleans 7]

See Also

Passing parameters by value and reference
Structures
          Accessing Array and Structures

 

Whitepaper ] Terms and Conventions ] Release Notes 2.2 ] Problems You May Encounter ] Installation overview ] Installing on Irix ] Installing on Nt ] Licensing ] Scripting ] Utilities and Libraries ] Tools ] Tutorials ]

copyright Video-Collage Inc.