Вы можете передавать аргументы в качестве параметров когда вызываете из Visual FoxPro элемент управления ActiveX, COM-объект или динамически подключаемую библиотеку Visual FoxPro (FLL). Например, элемент управления ActiveX может принять аргументы при вызове одного из его методов. По аналогии, программа Visual FoxPro может вызвать функцию в своей библиотеке FLL и передать ей аргументы.

Visual FoxPro может передавать аргументы через параметры внешней библиотеки по значению и по ссылке. По умолчанию считается заданной команда SET UDFPARMS. Однако, некоторые переменные, такие как массивы, поля и выражения, передаются по значению. Более подробно о том, как изменить умалчиваемое значение для передачи аргументов, можно узнать в Passing Data to Parameters (Передача Данных через Параметры).

Ввиду того, что элементы управления ActiveX и COM объекты являются стандартными программами Windows, нет специальных механизмов по передаче в их параметры аргументов из программ Visual FoxPro. Код передачи аргументов библиотеке FLL можно писать так, как будто аргументы передаются из программ, написанных на языках C или C++.

Однако, функции библиотеки FLL используют FoxInfo структуру для получения аргументов из Visual FoxPro. FoxInfo структура включает в себя список функций библиотеки, количество и тип параметров, которые ожидает получить. Например, следующая FoxInfo структура принадлежит библиотеке с одной функцией, имеющей внутреннее имя dates, которая получает один Character параметр:

В  CopyCode imageКопировать код
FoxInfo myFoxInfo[] = {
{ "DATES", (FPFI) dates, 1, "C" }
};

Функции, которые вы определяете во внешней библиотеке в действительности получают только один параметр - указатель на блок параметров. Блок параметров, определенный в структуре ParamBlk, хранит всю информацию о параметрах, которые были переданы из функции вызова Visual FoxPro. Следующий код иллюстрирует формат, которому должна следовать ваша декларируемая функция:

В  CopyCode imageКопировать код
void function_name(ParamBlk *parm)

Например, определение функции dates выглядит так:

В  CopyCode imageКопировать код
void dates(ParamBlk *parm)

Структура ParamBlk состоит из целого, которое представляет собой количество параметров, со следующим за ним массивом объединенного параметра. Определение структуры включено в Pro_ext.h:

В  CopyCode imageКопировать код
/* Список параметров для библиотечной функции */
typedef struct {
short int pCount; /* количество переданных параметров */
Parameter p[1]; /* pCount parameters */
} ParamBlk;

Тип Parameter, включенный в структуру ParamBlk, является объединением структуры Value и структуры Locator. Вызов по значению оперирует со структурой Value, а вызов по ссылке - со структурой Locator. Эту структура предназначена для доступа к параметрам, переданным вашей функции при ее вызове из Visual FoxPro.

Следующая информация, выделенная из файла Pro_ext.h, показывает определение типа Parameter:

В  CopyCode imageКопировать код
/* Параметр для библиотечной функции */
typedef union {
Value val;
Locator loc;
} Parameter;

Определение Структуры Value

Если параметр передан в вашу функцию по значению, то для доступа к нему используйте структуру Value. Следующая структура Value выделена из файла Pro_ext.h:

В  CopyCode imageCopy Code
// Значение выражения.
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

Следующая таблица является справочником по значениям, которые Вы можете передать и получить в структуре Value для различных типов данных. Только указанные поля структуры могут быть использованы для этого типа данных.

Содержание структуры Value для различных типов данных
Тип данных Поле структуры Значение

Character

ev_type

'C'

 

ev_length

длина строки

 

ev_handle

MHANDLE для строки

Numeric

ev_type

'N'

 

ev_width

Ширина отображения

 

ev_length

Десятичные разряды

 

ev_real

Двойная точность

Integer

ev_type

'I'

 

ev_width

Высота отображения

 

ev_long

Длинное целое

Date

ev_type

'D'

 

ev_real

Дата1

Date Time

ev_type

'T'

 

ev_real

Дата + (секунды/86400.0)

Currency

ev_type

'Y'

 

ev_width

Ширина отображения

 

ev_currency

Денежное значение2

Logical

ev_type

'L'

 

ev_length

0 or 1

Memo

ev_type

'M'

 

ev_wdith

FCHAN

 

ev_long

Длина memo-поля

 

ev_real

Смещение memo-поля

General

ev_type

'G'

 

ev_wdith

FCHAN

 

ev_long

Длина поля general

 

ev_real

Смещение поля general

Object

ev_type

'O'

ev_object

идентификатор объекта

Null

ev_type

'0' (zero)

ev_long

Тип данных

1. Дата представлена как номер дня в Юлианском календаре с двойной точностью и с плавающей точкой, вычисленный с использованием Алгоритма 199 из Коллекции Алгоритмов ACM. 
2. Денежное значение - это длинное целое с неявной десятичной точкой перед последними четырьмя цифрами.

NoteЗамечание

ev_length - это только указатель истинной длины строки. Строка не может заканчиваться символом конца строки, поскольку сама может содержать вложенные null символы.

Определение Структуры Locator

Используйте структуру Locator для манипулирования параметрами переданными по ссылке. Следующая структура Locator выделена из файла Pro_ext.h:

В  CopyCode imageCopy Code
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

Следующая таблица является справочником по полям структуры Locator.

Поле Locator'а Применение поля

l_type

'R'

l_where

Номер таблицы, содержащей это поле или -1 для переменной.

l_NTI

Имя Табличного Индекса. Для внутреннего применения Visual FoxPro.

l_offset

Номер поля в таблице. Для внутреннего применения Visual FoxPro.

l_subs

Только для переменных - число индексов (0 - 2).

l_sub1

Только для переменных - первый индекс, если l_subs не равен 0.

l_sub2

Только для переменных - первый индекс, если l_subs не равен 2.

NoteЗамечание

Хорошей манерой при программировании является проверка типа параметра в ev_type для того, чтобы определять какие поля доступны из структуры Value.

Пример Организации Доступа к Параметрам в Библиотеке FLL

В следующем примере _StrCpy( ) используется для возврата в Visual FoxPro типа Character, который является конкатенацией двух Character параметров. Обратите внимание на то, что хотя описатель каждого параметра структуры Value использован как рабочая память для выполнения конкатенации, изменения в распределении этой памяти не влияют на аргумент Visual FoxPro, который был передан по значению.

(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.)

CopyCode imageКопировать код
#include <Pro_ext.h>

Example(ParamBlk *parm)
{
// сделаем структуру paramBlk легко управляемой путем
// использования клавишных комбинаций, определенных в #define
#define p0 (parm->p[0].val)
#define p1 (parm->p[1].val)

// убедимся, что памяти достаточно
if (!_SetHandSize(p0.ev_handle, p0.ev_length + p1.ev_length))
_Error(182); // "Недостаточно памяти"

// заблокируем описатели (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';

// конкатенируем строки, используя API-функцию _StrCpy
_StrCpy((char *)_HandToPtr(p0.ev_handle) + p0.ev_length,
_HandToPtr(p1.ev_handle));

// возвратим конкатенированную строку 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
};

См. также