HUGEARR.DLL Huge array support for Microsoft Visual Basic from Microsoft Product Support Services 5/30/91 HUGEARR.DLL is a dynamic-link library (DLL) which contains functions for creation, maintenance, and deletion of arrays larger than 64K from Microsoft Visual Basic version 1.00 for Windows. This DLL also gives the ability to create arrays with more than 32,767 (32K) elements per dimension, and to redimension arrays while preserving the data inside of the arrays. The following files are provided: HUGEARR.DLL, HUGEARR.BAS, HUGEARR.C, HUGEARR.DEF, HUGEARR.H, HUGEARR.TXT, MAKEFILE To use the functions in HUGEARR.DLL, simply copy the declarations contained in HUGEARR.BAS into your global module in Visual Basic and copy HUGEARR.DLL to your Windows directory. The functions can then be used like any other Windows DLL function. HUGEARR.DLL allocates memory using the Windows API function GlobalAlloc. This means that the largest array that can be allocated is 1 MB in standard mode, and 64 MB in 386 enhanced mode for Windows. The following routines are contained in HUGEARR.DLL. For a complete description of the parameters and/or return values of these routines, see Visual Basic's Declare statement for the routine in question in the file HUGEARR.BAS. HUGEARR.DLL Language Reference: ------------------------------ ------------------------------------------------------------------------- HugeDim: Action: Dimensions an array and returns a handle to that array. Syntax: HugeDim(recsize%, limit&) Argument Description -------- ----------- recsize% The size of each element in the array. (i.e. an integer would be 2, a double would be 8.) You can use the Len() function to determine the size of any data type if you are unsure. limit& The upper bound of the array. The lower bound of all arrays is 0, so for example: 'HugeDim(2, 10)' would create an integer array of elements 0 through 10. Remarks: ------- You should not try to create a huge array of variable-length strings, or of a user-defined type that contains variable-length strings. Visual Basic's string handling routines would not know of the existence of any string that was controlled by HUGEARR.DLL, and a UAE ("Unrecoverable Application Error") would probably result. Fixed-length strings are okay though. If the total size (in bytes) of the array is going to be bigger than 64K, the size of each element has to be an integer power of two (1, 2, 4, 8, and so forth.) This is necessary so that the no element of an array straddles a segment boundary. HugeDim returns a handle to the array that was created, and that handle is used when referring to that array with other commands. If an error occurred (such as out of memory), it will return a negative number. Error codes are detailed below under the section entitled 'Error Codes'. Example: ------- Sub Command1_Click() Dim hArray as integer Dim variable as SomeUserDefinedType hArray = HugeDim(Len(variable), 10) If hArray < 0 Then print "Error dimensioning array:"; hArray Stop End If . . . i% = HugeErase(hArray) End Sub ------------------------------------------------------------------------- HugeErase: Action: Erases an array that was previously dimensioned using HugeDim. Syntax: HugeErase(hArray%) Argument Description -------- ----------- hArray% The handle to the array. (The same handle that was returned by HugeDim.) Remarks: -------- You should be sure to HugeErase all arrays that were HugeDim'd. Failing to do so would cause the memory used by the array to not be freed up until the application quits. If many arrays are dimensioned but never erased memory would keep being allocated without being freed, eventually degrading system performance. Example: Refer to the example for HugeDim. ------------------------------------------------------------------------- HugeRedim: Action: Redimensions an array created with HugeDim to a different size. Syntax: HugeRedim(hArray%, limit&) Argument Description -------- ----------- hArray% The handle to the array to redimension. limit& The new upper bound of the array. Remarks: -------- HugeRedim, unlike Visual Basic's ReDim, preserves all the data in the array. If you want to erase the contents of the array, you should erase it and the dimension it again. If the size of the array would go over 64K when it is redimensioned, it is subject to the same size restrictions detailed in the discussion of HugeDim. You cannot change the size of the elements in the array, only the number of elements. Example: -------- Sub Command1_Click() . . i% = HugeRedim(hArray, 50) if i% < 0 then print "error redimensioning array:"; hArray stop End If e% = HugeErase(hArray) End Sub ------------------------------------------------------------------------- GetHugeEl, SetHugeEl: Action: Gets or sets the contents of an array element. Syntax: GetHugeEl(hArray%, el&, variable) SetHugeEl(hArray%, el&, variable) Argument Description -------- ----------- hArray% The handle to the array. el& The element of the array to set or get the data from. variable The variable to get into, or to set the array from. Remarks: -------- It is extremely important that the type for the variable passed to GetHugeEl or SetHugeEl matches that type of the variable used in the HugeDim statement, if the types are of different lengths, you will mostly likely get a UAE or overwrite other data. If you want to be sure that the types match you can use the Alias keyword when you declare the function to introduce type checking. Refer to the section below entitled 'Aliasing' for more information on aliases. Example: -------- Sub Command2_Click() . . . hArray = HugeDim(len(i%), 10) If hArray < 0 Then Stop e% = SetHugeEl(hArray, 1, 54%) ' puts 54 into element #1 If e% < 0 Then Stop ' check error code e% = GetHugeEl(hArray, 1, i%) ' get element #1 into i% Print i% e% = HugeErase(hArray) End Sub ----------------------------------------------------------------------- HugeInt: HugeLong: HugeSingle: HugeDouble: HugeCurrency: Action: Retrieves an element from an array of a given type. Syntax: HugeInt(hArray%, el&) HugeLong(hArray%, el&) HugeSingle(hArray%, el&) HugeDouble(hArray%, el&) HugeCurrency(hArray%, el&) Argument Description -------- ----------- hArray% The handle to the array. el& The element to retrieve. Remarks: -------- This family of functions is provided as a shortcut alternative to GetHugeEl to retrieve a given data type while in an expression. For example: value = HugeDouble(hArray, 0) * HugeDouble(hArray, 1) The example above could have been done using GetHugeEl; however, the values returned by the two HugeDouble calls would have to be assigned to variables, and then the variables would be used in the expression. The example below expands more on this. IMPORTANT: None of these functions return error codes, so you should use them only if you are positive that the value of hArray% and el& are legal values. If a error does occur (such as a "Subscript Out of Range"), you will get meaningless results. You should use GetHugeEl if you need to be able to check error codes. Example: -------- Sub Command3_Click() Dim hArray As Integer hArray = HugeDim(len(i%), 10) If hArray < 0 Then Stop e% = SetHugeEl(hArray, 0, 3%) ' Put 3 in element #0 If e% < 0 Then Stop ' Check for errors e% = SetHugeEl(hArray, 1, 4%) ' Put 4 in element #1 If e% < 0 Then Stop e% = GetHugeEl(hArray, 0, i%) ' Get value of element #0 If e% < 0 Then Stop e% = GetHugeEl(hArray, 1, j%) ' Get value of element #1 If e% < 0 Then Stop Print Sqr(i% ^ 2 + j ^ 2) ' Alternate (and faster) ' way of doing the above. Print Sqr(HugeInt(hArray, 0) ^ 2 + HugeInt(hArray, 1) ^ 2) e% = HugeErase(hArray) End Sub ------------------------------------------------------------------------- HugeUbound: Action: Returns the upper bound of a give array. Syntax: HugeUbound(hArray%) Argument Description -------- ----------- hArray% The handle to the array. Remarks: -------- This function is the same as Basic's 'Ubound' function. It is used to return the current upper bound of an array. If HugeUbound returns an negative value, it represents an error code. Example: -------- Sub Command4_Click() Dim hArray as integer hArray = HugeDim(len(i%), 23) If hArray < 0 Then Stop for j=0 to HugeUbound(hArray) ' Initialize array to 10's e% = SetHugeEl(hArray, j, 10%) If e% < 0 Then Stop Next j . . . End Sub ------------------------------------------------------------------------ NumHugeArrays: Action: Returns the number of free huge arrays available. Syntax: NumHugeArrays Remarks: ------- This command is included mostly for debugging purposes. It is used to find out how many array could be dimensioned at that time by the program. Example: -------- Sub Command5_Click() Debug.Print NumHugeArrays End Sub --------------------------------------------------------------------------- Error Codes: The following functions return error codes as described below: HugeDim, HugeErase, HugeRedim, GetHugeEl, SetHugeEl, HugeUbound The possible error codes are: 0 The function was successful. -1 "Out of Memory" There is not enough global memory for the HugeDim or HugeRedim -2 "To Many Arrays" There are no free arrays left to be dimensioned. -3 "Bad Element Size" The array that you are trying to dimension is greater than 64K, and the element size is not an integer power of 2. -4 "Subscript out of Range" The array element you are trying to access is outside the bounds of the array. -5 "Illegal Array Handle" The array that was referenced is not a valid array. Either it is not dimensioned, or the handle value is illegal. ------------------------------------------------------------------------ Aliasing: The GetHugeEl and SetHugeEl functions transfer data back and forth from an array. Because these functions must work with any data type, they are declared 'As Any' in their declarations. This has the disadvantage that it defeats Basic's built-in type checking, and allows the posibility of passing the wrong data type. To work around this potential problem, you can use Basic's 'Alias' keyword in the declaration. For example, if you wanted GetHugeEl to work with the data type 'UserType', you might rename the function to 'GetUserType', and alias it to 'GetHugeEl'. The declaration for GetHugeEl contained in "HUGEARR.BAS" is: Declare Function GetHugeEl Lib "hugearr.dll" (ByVal Index%, ByVal el&, buffer As Any) As Integer To force Basic to do type checking on the call, you would rewrite the declaration to be: Declare Function GetUserType Lib "hugearr.dll" Alias "GetHugeEl" (ByVal Index%, ByVal el&, buffer As UserType) As Integer Note that the 'buffer As Any' has been changed to 'buffer As UserType'. Because the function no longer has the 'As Any' type Basic will be able to raise an error if you try to pass the wrong data type. A function can be aliased any number of times, so you may want to create an alias for each data type that you are using. ----------------------------------------------------------------------- Constants: The SetHugeEl routine is used to assign values to an array. For example, the following statement i% = SetHugeEl(hArray, 1, v%) would assign the value stored in v% to element #1 of the array hArray. However, a problem can arise when you try to use a constant in place of the 'v%' above. For example: i% = SetHugeEl(hArray, 1, 15) In this case, Visual Basic would assume that the number 15 is an integer constant and would pass a pointer to an integer to the SetHugeEl routine; even if hArray is a (for instance) array of double-precision numbers. To work around this potential problem, you should always use a type suffix when passing constants to SetHugeEl. If you wanted to assign the value of 15 to a double precision array, you would use the statement: i% = SetHugeEl(hArray, 1, 15#) -------------------------------------------------------------------------- HUGEARR.DLL Memory and Capacity: HUGEARR.DLL allocates memory using the Windows API function GlobalAlloc. This means that the largest array that can be allocated is 1 MB in standard mode, and 64 MB in 386 enhanced mode. If you forget to HugeErase an array that was allocated with HugeDim, Windows will automatically deallocate the memory after your application terminates. However, HUGEARR.DLL keeps the information it needs to maintain the arrays in it's own private area. This means that any array which is not HugeErase'd will not have it's information released, and the array will not be marked as free. If two applications are both using the DLL, and the first application HugeDim's all of the arrays and then quits without HugeEraseing them, the second application will not be able to create any arrays.