共用方式為


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
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

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