Data Structures

InstallShield 2016 » InstallScript Language Reference

A data structure is a named data item that consists of logically related variables, called members. In many programming languages, data structures are called records, and the variables within records are called fields. In InstallScript, data structures are similar in form and function to structures in C. They can include members of different data types, and those members within the data structure can be referenced directly by using the member operator (.).

Defining a Data Structure

To define a data structure, use the keyword typedef and follow it with the name of the data structure. Fields in the structure must be defined within a begin...end block, as shown in the example below, which defines a structure called EMPLOYEE. The data structure EMPLOYEE includes three variables: a string variable for an employee’s name, a string variable for an employee’s department, and a number variable for an employee’s phone extension.

    typedef EMPLOYEE

    begin

        STRING szName[50];

        STRING szDepartment[50];

        NUMBER nExtension;

    end;

When you define a data structure, you are actually defining a new data type. To use a data structure within a program, you must first declare a variable of that type. To do that, use the name of the defined data structure as the data type and follow it with an identifier, as shown in the example below, which creates a variable of type EMPLOYEE.

    EMPLOYEE structEmployee;

To reference members of the structure variable, use the member operator ( . ). In the example below, literal values are assigned to each member of structEmployee.

     structEmployee.szName = "I. S. Coder";

     structEmployee.szDepartment = "Development";

     structEmployee.nExtension = 555;

Restrictions

The following restrictions apply to structures:

You cannot assign the contents of one structure to another structure with the assignment operator, as in newstruct = struct1. Instead, you must copy the structure one element at a time.
You must specify the size of all STRING declarations in a structure—the autosizing functionality in InstallScript does not work in typedef statements.
You cannot declare a structure within a function.
You cannot use the BYREF operator with a structure, nor can you pass a structure member in a parameter that was declared with the BYREF operator. To modify a member of a user-defined structure in a user-defined function, pass a pointer to the structure and then use the Structure Pointer Operator (->) to access the data within the function.
Referencing a pointer before the address of a data structure has been assigned to the pointer results in a run-time error.

Unicode Support for Structures

Structures in InstallScript can contain any basic data type, including strings and pointers, or other structures. If a structure needs to contain a Unicode string and the structure is passed to an external DLL, the InstallScript engine can distinguish between string member types in a structure, and then size the structure and calculate member offsets correctly. String members that need to be stored and passed as Unicode can be declared with the WSTRING type.

Note that if a Unicode string is declared with the STRING type and the string is used in a structure, the InstallScript engine treats the string as ANSI when passing it to an external DLL. As a result, the size of the structure and member offsets in the structure could be wrong, causing the DLL to incorrectly read or write data related to the structure.

Pointer members in structures can be declared as WPOINTER. This enables you to store pointers to Unicode strings in a structure.

Examples

Like C, InstallScript allows you to nest or embed data structures. For example, suppose you wanted to create a structure that could be used to define the upper-left and lower-right coordinates of a rectangle. Each coordinate consists of two values: an x value and a y value. You could define a structure that consists of four members: the x and y positions of the upper-left corner and the x and y positions of the lower-right corner.

However, since each x and y pair is a logical unit, you might first define a structure called POINT that has two members defining a vertical and horizontal position. Then you could define a structure called RECT that includes two members of type POINT, one to define the upper left coordinate, another to define the lower right coordinate. These two structures are shown below:

    // Define a point structure.

    typedef POINT

    begin

        SHORT nX;

        SHORT nY;

    end;

 

    // Use nested point structures to define a rectangle structure.

    typedef RECT

    begin

        POINT UpperLeft;

        POINT LowerRight;

    end;

When a structure is to be referenced by a pointer to that structure, you must use the structure pointer operator ( -> ) to address members of the structure. In the example below, a variable of type RECT is declared, a pointer to the structure is declared, and then the address of the RECT variable is assigned to the pointer. Finally, the structure pointer operator is used to initialize each member to 0.

    RECT Rectangle;

    RECT POINTER pRect;

 

    pRect = &Rectangle;

    pRect->UpperLeft.nX  = 0;

    pRect->UpperLeft.nY  = 0;

    pRect->LowerRight.nX = 0;

    pRect->LowerRight.nY = 0;

The following script presents a more complete demonstration of structure pointers, nested structures, and structure pointer dereferencing with the structure pointer operator.

    // Use a structure to define a point.

    typedef POINT

    begin

        SHORT nX;

        SHORT nY;

    end;

 

    // Use nested structures to define a rectangle.

    typedef RECT

    begin

        POINT UpperLeft;

        POINT LowerRight;

    end;

 

    // Declare a rectangle structure variable.

    RECT Rectangle;

 

    // Define a pointer to a RECT structure.

    RECT POINTER pRect;

 

    // Declare a function to display structure contents.

    prototype ShiftRectBy2(RECT POINTER);

 

    . . .

 

    // Get a pointer to the Rectangle structure.

    pRect = &Rectangle;

 

    // Define the points that define the rectangle.

    pRect->UpperLeft.nX = 100;

    pRect->UpperLeft.nY = 400;

    pRect->LowerRight.nX = 200;

    pRect->LowerRight.nY = 100;

 

    // Display point x and y values before calling ShiftRectBy2.

    SprintfBox (INFORMATION,

               "BEFORE calling ShiftRectBy2",

               "pRect->UpperLeft.nX  = %d\n" +

               "pRect->UpperLeft.nY  = %d\n" +

               "pRect->LowerRight.nX = %d\n" +

               "pRect->LowerRight.nY = %d\n",

               pRect->UpperLeft.nX,

               pRect->UpperLeft.nY,

               pRect->LowerRight.nX,

               pRect->LowerRight.nY

               );

 

    // Shift the rectangle 2 up and 2 to the right.

    ShiftRectBy2(pRect);

 

    // Display point x and y values after calling ShiftRectBy2.

    SprintfBox (INFORMATION,

               "AFTER calling ShiftRectBy2",

               "pRect->UpperLeft.nX  = %d\n" +

               "pRect->UpperLeft.nY  = %d\n" +

               "pRect->LowerRight.nX = %d\n" +

               "pRect->LowerRight.nY = %d\n",

               pRect->UpperLeft.nX,

               pRect->UpperLeft.nY,

               pRect->LowerRight.nX,

               pRect->LowerRight.nY

               );

 

    // Define the rectangle shifting function.

    function ShiftRectBy2(pR)

    begin

        pR->UpperLeft.nX = pR->UpperLeft.nX + 2;

        pR->UpperLeft.nY = pR->UpperLeft.nY + 2;

        pR->LowerRight.nX = pR->LowerRight.nX + 2;

        pR->LowerRight.nY = pR->LowerRight.nY + 2;

    end;

See Also