Passing and Reception of Parameters
When your program is called from Visual FoxPro, it can receive parameters. For example, an ActiveX control might receive parameters when one of its methods is invoked. Similarly, a Visual FoxPro program might call a function in your FLL library and pass parameters to it.
Visual FoxPro can pass parameters to your program by value or by reference. By default, parameters respect the setting made with SET UDFPARMS. Other variables (such as arrays or fields) and expressions are passed by value.
To force a parameter to be passed by reference, precede the variable reference with the @ operator. To force a parameter to be passed by value, enclose it in parentheses.
Note In Visual FoxPro, individual array elements are always passed by value. When SET UDFPARMS is set to VALUE and no array element is specified, the array name by itself refers to the first element of the array (unless it is prefixed with @).
Because ActiveX controls and COM objects are Windows-standard programs, no special mechanism is required to pass parameters from Visual FoxPro and your program. You can write the program as if it were receiving parameters from any C or C++ program.
In contrast, functions in an FLL library use the FoxInfo structure to receive data from Visual FoxPro. The FoxInfo structure lists your library functions and the number and type of parameters they expect. For example, the following FoxInfo
structure belongs to a library with one function, internally called dates
, that accepts one Character parameter:
FoxInfo myFoxInfo[] = {
{ "DATES", (FPFI) dates, 1, "C" }
};
Functions you define in your libraries actually receive only one parameter, a pointer to the parameter block. This parameter block, defined in the ParamBlk
structure, holds all the information about the parameters that were passed from the Visual FoxPro function call. Your function declaration follows this format:
void function_name(ParamBlk *parm)
For example, the function definition for dates
is:
void dates(ParamBlk *parm)
The ParamBlk
structure consists of an integer that represents the number of parameters, immediately followed by an array of parameter unions. The structure definition is included in Pro_ext.h:
/* A parameter list to a library function. */
typedef struct {
short int pCount; /* number of parameters passed */
Parameter p[1]; /* pCount parameters */
} ParamBlk;
The Parameter
typedef included in the ParamBlk
structure is a union of a Value structure and a Locator structure. Call by value is handled by a Value structure; call by reference is handled by a Locator structure. You use these structures to access the parameters passed to your function when the function is called in Visual FoxPro.
The following information is extracted from the file Pro_ext.h and shows the definition of the Parameter
type:
/* A parameter to a library function. */
typedef union {
Value val;
Locator loc;
} Parameter;
Value Structure Definition
If a parameter is passed to your function by value, use the Value structure to access it. The following Value
structure definition is extracted from the Pro_ext.h file:
// An expression's value.
Typedef struct {
char ev_type;
char ev_padding;
short ev_width;
unsigned ev_length;
long ev_long;
double ev_real;
CCY ev_currency;
MHANDLE ev_handle;
ULONG ev_object;
} Value;
Value Structure Fields
The following table is a guide to the values you can pass and receive in the Value structure for different types of data. Only the structure fields listed for a data type are used for that data type.
Contents of Value structure for different data types
Data type | Structure field | Value |
---|---|---|
Character |
|
'C' |
|
string length | |
|
MHANDLE to string | |
Numeric |
|
'N' |
|
Display width | |
|
Decimal places | |
|
Double precision | |
Integer |
|
'I' |
|
Display width | |
|
Long integer | |
Date |
|
'D' |
|
Date1 | |
Date Time |
|
'T' |
|
Date + (seconds/86400.0) | |
Currency |
|
'Y' |
|
Display width | |
|
Currency value2 | |
Logical |
|
'L' |
|
0 or 1 | |
Memo |
|
'M' |
|
FCHAN | |
|
Length of memo field | |
|
Offset of memo field | |
General |
|
'G' |
|
FCHAN | |
|
Length of general field | |
|
Offset of general field | |
Object |
|
'O' |
|
Object identifier | |
Null |
|
'0' (zero) |
|
Data type |
1. The date is represented as a double-precision floating-point Julian day number calculated using Algorithm 199 from Collected Algorithms of the ACM.
2. The currency value is a long integer, with an implied decimal point in front of the last four digits.
Note
ev_length
is the only true indicator of a string's length. The string can't have a null terminator because the string can contain embedded null characters.
Locator Structure Definition
Use the Locator structure to manipulate parameters passed by reference. The following Locator
structure definition is extracted from the Pro_ext.h file:
typedef struct {
char l_type;
short l_where, /* Database number or -1 for memory */
l_NTI, /* Variable name table offset*/
l_offset, /* Index into database*/
l_subs, /* # subscripts specified 0 <= x <= 2 */
l_sub1, l_sub2; /* subscript integral values */
} Locator;
Locator Structure Fields
The following table is a guide to the fields in the Locator structure.
Locator field | Field use |
---|---|
|
'R' |
|
The number of the table containing this field, or – 1 for a variable. |
|
Name Table Index. Visual FoxPro internal use. |
|
Field number within table. Visual FoxPro internal use. |
|
For variables only, the number of subscripts (0 – 2). |
|
For variables only, the first subscript if l_subs is not 0. |
|
For variables only, the second subscript if l_subs is 2. |
Note It's good programming practice to check for the parameter type in
ev_type
to help determine which fields to access from the Value structure.
An Example of Accessing Parameters in an FLL Library
The following example uses _StrCpy( )
to return a Character type to Visual FoxPro that's the concatenation of its two Character parameters. Notice that although the handle of each parameter's Value structure is used as working memory to perform the concatenation, changes to this memory allocation don't affect the Visual FoxPro argument that was passed by value.
#include <Pro_ext.h>
Example(ParamBlk *parm)
{
// make the paramBlk structure easier
// to manage by using #define shortcuts
#define p0 (parm->p[0].val)
#define p1 (parm->p[1].val)
// make sure there is enough memory
if (!_SetHandSize(p0.ev_handle, p0.ev_length + p1.ev_length))
_Error(182); // "Insufficient memory"
// lock the handles
_HLock(p0.ev_handle);
_HLock(p1.ev_handle);
// convert handles to pointers and make sure the
// strings are null-terminated
((char *)_HandToPtr(p0.ev_handle))[p0.ev_length] = '\0';
((char *)_HandToPtr(p1.ev_handle))[p1.ev_length] = '\0';
// concatenate strings using the API function _StrCpy
_StrCpy((char *)_HandToPtr(p0.ev_handle) + p0.ev_length,
_HandToPtr(p1.ev_handle));
// return the concatenated string to Visual FoxPro
_RetChar(_HandToPtr(p0.ev_handle));
// unlock the handles
_HUnLock(p0.ev_handle);
_HUnLock(p1.ev_handle);
}
FoxInfo myFoxInfo[] = {
{"STRCAT", Example, 2, "CC"},
};
FoxTable _FoxTable = {
(FoxTable *) 0, sizeof(myFoxInfo)/sizeof(FoxInfo), myFoxInfo
};
See Also
Adding Visual FoxPro API Calls | Return of a Value to Visual FoxPro | Accessing the Visual FoxPro API | Passing of Parameters to Visual FoxPro API Functions | Extending Visual FoxPro with External Libraries | API Library Construction