Release 10.1A: OpenEdge Development:
Programming Interfaces

> ## Passing arrays as parameters

> This section describes how you can pass arrays as parameters to and from DLL functions.

> Note: You cannot pass an array of indeterminate extent to a DLL.

> ##### INTEGER and DECIMAL arrays

> When a DLL Function requires an array of type `BYTE`, `SHORT`, `UNSIGNED-SHORT`, `INT`, `LONG`, `FLOAT`, or `DOUBLE`, you can pass an array of the appropriate Progress type (`INTEGER` or `DECIMAL`) as a parameter. You can use any parameter mode (`INPUT`, `INPUT-OUTPUT`, or `OUTPUT`). For the data type in the prototype, you can use just the type (for example, `LONG`) or you can specify it with the `HANDLE` `TO` option (for example, `HANDLE` `TO`). Progress always passes the array of values as a pointer so the `HANDLE` `TO` option is redundant, as it is with any `INPUT-OUTPUT` or `OUTPUT` parameter.

> Here is an example C Code Prototype for a function called updateCounts:

>     updateCounts(short * parray);

> Here is the equivalent Progress 4GL Prototype for the updateCounts procedure.

>     PROCEDURE updateCounts EXTERNAL "myApp.dll" PERSISTENT:
>          DEFINE INPUT-OUTPUT PARAMETER parray AS SHORT.
>     END.

> Here is the 4GL statement that executes the updateCounts procedure:

>     DEFINE VARIABLE cnts AS INTEGER EXTENT 5.
>          	.
>          	.
>          	.
>     RUN updateCounts (cnts).

> ##### CHARACTER and LONGCHAR arrays

> If the DLL requires an array of strings as `INPUT` which is represented by an array of pointers to strings, you can pass a Progress `CHARACTER` or `LONGCHAR` array. You can do the same if it is an `INPUT-OUTPUT` parameter, however, this is not recommended. If the DLL updates the data such that the output string is longer than the input string, this can result in a memory exception or other unpredictable behavior. Therefore, for `INPUT-OUTPUT` parameters you should use a `MEMPTR` array, described in the "MEMPTR arrays" section.

> Also, just as you cannot pass `CHARACTER` or `LONGCHAR` `OUTPUT` parameters to a DLL, you also cannot pass a `CHARACTER` or `LONGCHAR` array as an `OUTPUT` parameter. If the DLL requires an array of character buffers that it will modify or if the DLL allocates memory for a set of strings and returns them as an array of pointers, you should use a `MEMPTR` parameter.

> As with the `INTEGER` and `DECIMAL`types of arrays, the data type in the prototype can be either just the type (for example, `CHARACTER`) or you can specify it with the `HANDLE` `TO` option.

> Here is an example C Code Prototype for a function called `nameLookup`:

>     nameLookup(char **ppStrArray, char *pfindName);

> Here is the equivalent Progress 4GL Prototype for the `nameLookup` procedure:

>     PROCEDURE nameLookup EXTERNAL "myApp.dll" PERSISTENT:
>          DEFINE INPUT PARAMETER ppStrArray AS HANDLE TO CHARACTER.
>          DEFINE INPUT PARAMETER pfindName  AS CHARACTER.
>     END.

> Here is the 4GL statement that executes the `nameLookup` procedure:

>     DEFINE VAR names AS CHARACTER EXTENT 50.
>     DEFINE VAR findName AS CHARACTER.
>          .
>          .
>          .
>     RUN nameLookup(names, findName).

> ##### MEMPTR arrays

> If the DLL requires an array of pointers, where each pointer either points at a string or a structure, you can pass a Progress `MEMPTR` array. For `INPUT` or `INPUT-OUTPUT` parameters, you initialize each `MEMPTR` as appropriate to contain the string or structure to pass for `INPUT`. If it is an `INPUT-OUTPUT` parameter, you must insure that the allocated size (that is, the size set by `SET-SIZE`) is large enough to hold any expected output value, not just large enough to hold the input value. For an `OUTPUT` parameter, if the DLL expects an array of pointers to allocated buffers, you must use `SET-SIZE` to the required size for each `MEMPTR` in the array. If the DLL allocates memory for a set of strings or structures and returns them as an array of pointers, you must set each `MEMPTR` to at least the size of a pointer (for example, 4 or 8 bytes depending on the platform). You then use the `GET-POINTER-VALUE` and `SET-POINTER-VALUE` functions to access the data on return. (For more information on the `GET-` and `SET-POINTER-VALUE` functions, see OpenEdge Development: Progress 4GL Reference .) If you want to pass `NULL` as one or more of the pointers, the corresponding `MEMPTR` in the array can be a null `MEMPTR`, meaning that it is either uninitialized or you did a `SET-SIZE` on it to set it to zero length. For information on passing a `MEMPTR` parameter, see the "Using MEMPTR variables as parameters" section.

> Here is an example C Code Prototype for a function called `getNames`:

>     getNames(char **pnameList);

> Here is the equivalent Progress 4GL Prototype for the `getNames` procedure. In this case, the DLL does not allocate the buffer, but expects to be passed an array of buffer pointers:

>     PROCEDURE getNames EXTERNAL "myApp.dll" PERSISTENT:
>          DEFINE OUTPUT PARAMETER names AS MEMPTR.
>     END.

> Here is the 4GL statement that executes the `getNames` procedure:

>     DEFINE VAR names AS MEMPTR EXTENT 10.
>     DEFINE VAR ix AS INTEGER.
>     DO ix = 1 TO 10:
>          SET-SIZE(names[ix]) = 50.
>     END.
>     RUN getNames(names).
>     DO ix = 1 TO 10:
>          DISPLAY GET-STRING(names[ix]).
>     END.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095