Parameters in External Libraries
You can pass arguments to parameters when Visual FoxPro calls an ActiveX control, COM object, or Visual FoxPro dynamic-link library (FLL). For example, an ActiveX control might accept arguments when calling one of its methods. Similarly, a Visual FoxPro program might call a function in your FLL library and pass arguments to it.
Visual FoxPro can pass arguments to parameters in an external library by value or by reference. By default, the setting of the SET UDFPARMS command is respected. However, other variables, such as arrays or fields, and expressions are passed by value. For information about how to change the default way of passing arguments, see Passing Data to Parameters.
Because ActiveX controls and COM objects are Windows-standard programs, no special mechanism is required to pass arguments from Visual FoxPro to parameters in an ActiveX control or COM object. You can write library code as if it were receiving arguments from any C or C++ program.
However, functions in an FLL library use the FoxInfo structure to receive data from Visual FoxPro. The FoxInfo structure lists 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 external libraries actually receive only one parameter, a pointer to the parameter block. This parameter block, defined in the ParamBlk structure, stores all the information about the parameters that were passed from the Visual FoxPro function call. The following code illustrates the format that your function declaration should follow:
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 |
ev_type |
'C' |
|
ev_length |
string length |
|
ev_handle |
MHANDLE to string |
Numeric |
ev_type |
'N' |
|
ev_width |
Display width |
|
ev_length |
Decimal places |
|
ev_real |
Double precision |
Integer |
ev_type |
'I' |
|
ev_width |
Display width |
|
ev_long |
Long integer |
Date |
ev_type |
'D' |
|
ev_real |
Date1 |
Date Time |
ev_type |
'T' |
|
ev_real |
Date + (seconds/86400.0) |
Currency |
ev_type |
'Y' |
|
ev_width |
Display width |
|
ev_currency |
Currency value2 |
Logical |
ev_type |
'L' |
|
ev_length |
0 or 1 |
Memo |
ev_type |
'M' |
|
ev_wdith |
FCHAN |
|
ev_long |
Length of memo field |
|
ev_real |
Offset of memo field |
General |
ev_type |
'G' |
|
ev_wdith |
FCHAN |
|
ev_long |
Length of general field |
|
ev_real |
Offset of general field |
Object |
ev_type |
'O' |
|
ev_object |
Object identifier |
Null |
ev_type |
'0' (zero) |
|
ev_long |
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 |
---|---|
l_type |
'R' |
l_where |
The number of the table containing this field, or – 1 for a variable. |
l_NTI |
Name Table Index. Visual FoxPro internal use. |
l_offset |
Field number within table. Visual FoxPro internal use. |
l_subs |
For variables only, the number of subscripts (0 – 2). |
l_sub1 |
For variables only, the first subscript if l_subs is not 0. |
l_sub2 |
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
Tasks
How to: Add Visual FoxPro API Calls
How to: Return Values from ActiveX Controls and FLL Libraries
Reference
Passing Parameters to Visual FoxPro API Functions
Other Resources
Accessing the Visual FoxPro API