Was this helpful?
Call4GL Parameter Descriptors
The ByValParamDesc and ByRefParamDesc parameters point to parameter descriptors. The ByVal and ByRef descriptors are both structured the same way. The ByVal and ByRef parameters have been separated into two groups so that COM can marshal them differently.
A ParamDesc is a VARIANT structure composed of nested arrays of VARIANTs that describe the signature of the 4GL procedure being called. At the very top level, a ParamDesc is simply a single VARIANT. This VARIANT contains a two-dimensional array of VARIANTs, with two rows and as many columns as there are parameters you want to map to in the 4GL procedure signature.
The top row of the descriptor contains the names of the 4GL parameters (as BSTR values). The ordering of the columns in the descriptor defines how the corresponding columns of the data array will be mapped to the named 4GL parameters.
The second row of the descriptor is only used when necessary to further describe parameters that have structured types (that is, a user class or array of user class). The cell under the name of the structured parameter will contain a nested descriptor that defines the positional-to-name mapping for the attributes of the relevant user class. Nested descriptors can also contain further nested descriptors to describe the mapping to nested user classes to basically any number of levels.
For example, consider a 4GL signature similar to the ubiquitous “helloworld” example, but expanded to illustrate the use of user classes. (For simplicity, treat all the parameters as ByRef so they will all be in one descriptor.)
Here are the user class definitions:
Userclass Cinrec
(
    Input_Column_1    = varchar(100) not null,
    Input_Column_2    = varchar(100) not null,
    ...               = /* other attributes that can be ignored */
 )
Userclass Coutrec
(
    Output_Column_1    = varchar(100) not null,
    Output_Column_2    = varchar(100) not null,
    ...                = /* other attributes that can be ignored */
)
And the 4GL procedure:
Procedure helloworld
(
    MyScalar     = integer not null,
    MyInArray    = array of Cinrec,
    MyOutArray   = array of Coutrec
) =
{
    /*
    ** Swap columns of the first row of input and return as output.
    */
    MyOutArray[1].Output_Column_1 = MyInArray[1].Input_Column_2;
    MyOutArray[1].Output_Column_2 = MyInArray[1].Input_Column_1;

    /*
    ** Increment the scalar and return it byref.
    */
    MyScalar = MyScalar + 1;
}
The ByRefParamDesc for this signature would contain three columns, corresponding to the three parameters of the signature. Descriptors for the user classes would have two columns, corresponding to the two relevant attributes of each user class. The finished nested ByRefParamDesc would look like this:
(The gray cells simply contain VT_EMPTY, the default initialization value.)
Here is an example of how to create this nested structure using VBScript:
Dim ByRefParamDesc(1,2)
Dim InArrayDesc(1,1)
Dim OutArrayDesc(1,1)

InArrayDesc(0,0) = “Input_Column_1”
InArrayDesc(0,1) = “Input_Column_2”

OutArrayDesc(0,0) = “Output_Column_1”
OutArrayDesc(0,1) = “Output_Column_2”
Top-level parameter names go across the top row:
ByRefParamDesc(0,0) = “MyScalar”
ByRefParamDesc(0,1) = “MyInArray”
ByRefParamDesc(0,2) = “MyOutArray”
Nested descriptors for the complex parameters go on the second row:
ByRefParamDesc(1,1) = InArrayDesc
ByRefParamDesc(1,2) = OutArrayDesc
Last modified date: 12/20/2023