网乐原科技

直播中

news center新闻中心
首页 > 资讯中心 > 软件技术

Visual FoxPro扩展程序库的编写要点

发布时间:2008-08-09     阅读数: 次       来源:网乐原科技
摘要:本文介绍用C/C++编制Visual FoxPro扩展程序库的基本要点,并给出一些参数传递的例子。
  关键词:Visual FoxPro扩展程序库</P><P>  Visual FoxPro的扩展程序库由C或C++编写,可以访问Visual FoxPro的“应用程序接口”(API),大大扩展了Visual FoxPro的原有功能。本文即介绍编制扩展程序库的基本要点。
  编制扩展程序库有一定的软件要求。首先,由于Visual FoxPro是一个32位的应用程序,所以必须使用一32位编译器来连编该程序库,笔者推荐使用Microsoft VisualC++TM4.1版。其次需要Visual FoxPro“应用程序接口”的头文件(PRO_EXT.H)以及导入库(WINAPIMS.LIB),这两个文件均在Visual FoxPro的API子目录下。
  对于有C语言编程经验的程序员来说,写扩展程序库的难点在于要搞清:扩展程序库本身的框架、数据类型和数据结构以及扩展程序库与Visual FoxPro环境的数据交换约定。下面主要介绍这三点。</P><P>一、 扩展程序库的基本结构</P><P>程序库由四部分组成:</P><P>
1、#include 语句</P><P>
#include <pro_ext.h>;
2、函数定义
void Function _ Name (ParamBlk*parm)
{
\\函数代码
}
3、FoxInfo结构
FoxInfo myFoxInfo[]\{
{"FUNCTION_N",(FPFI)Function_Name,
ParmCount,ParmTypes},
};
  FoxInfo结构用于在Visual FoxPro和库之间传递函数名和参数描述信息。“myFoxInfo"为FoxInfo型的变量。注意在该数组中可以包含多个FoxInfo结构行。ParmCount指定在ParmTYpes字符串中描述的参数个数,或者下列标志值之一:
值说明
INTERNAL 指明该函数不能直接从Visual FoxPro调用
CALLONLOAD 指明该函数在加载时调用。
CALLONUNLOAD 指明该函数的卸载库,或发出VisualFoxPro的QUIT命 令时调用
注:CALLONLOAD和CALLONUNLOAD均不能调用那些返回结果给Visual FoxPro的函数。
ParmTYpes描述每个参数的数据类型。下表列出ParmTYpes的有效值。
值描述
““ 无参数
“?” 能传递任意类型
“C” 字符型参数
“D” 日期型参数
“I” 整型参数
“L” 逻辑型参数
“N” 数值型参数
“R” 引用
“T” 日期时间型参数
“Y” 货币型参数
4、Foxtable 结构
FoxTable myFoxTable={
(FoxTable *)0,sizeof(myFoxInfo) /
sizeof(FoxInfo),myFoxInfo
}
  该结构第一个参数是Visual FoxPro内部使用的一个指针,必须初始化为0;第二个参数是该程序库定义的Visual FoxPro外部例程数目;第三个参数实际为该程序库FoxInfo结构的变量名。如读者的FoxInfo型变量名为myFoxInfo,建议读者直接使用上面这个例子。</P><P>二、Visual FoxPro API数据类型与数据结构</P><P>1、数据类型
  Visual FoxPro API定义的数据类型见下表
数据类型说明
EDLINE 用于编辑窗口中打开的文件,指明文件中某一行的行号,首行为1。
EDPOS 用于编辑窗口中打开的文件,指明文件中某个字符的偏移位置 。
FCHAN 文件通道。每个由Visual FoxPro打开的文件,或通过API用 _FCreate()和_FOpen()打开的文件,都被分配一个FAHAN FPFI 指向一个返回一个整数值的函数的32位指针。
ITEMID 为菜单中某一命令指定的唯一标识。
MENUID 指定给一个菜单的唯一标识。
MHANDLE 一个唯一标识,每一个由Visual FoxProw分配的内存块,或通过API用_AllocHand()分配的内存块都具有这样一个标识。可以使用_HandToPtr()返回引用到它的指针。
NTI 名称表索引。每个内存变量和表字段的名称在该表中都有一项 。
WHANDLE 窗口句柄。每一个由Visual FoxPro打开的窗口,或者通过API 用_Wopen()打开的窗口都有这样一个唯一的标识。
2、数据结构
Visual FoxPro API定义的数据结构见下表:
Visual FoxPro API数据类型
结构说明
EventRec 一个结构,用于描述在某个给定的时刻系统正在进行的操作。
FoxInfo 前面已介绍
FoxTable 前面已介绍
Locator 在“数据交换”中详细介绍
ParamBlk 在“数据交换”中详细介绍
Parameter 在“数据交换”中详细介绍
Point 一个结构,定义了屏幕上一个点的水平和垂直坐标。坐标按行号和列号指定。
Rect 一个结构,定义了屏幕上一个矩形的坐标。该矩形的左上角由 (top,left)定义,右下角由(bottom-1,right-1)定义。坐标按 行号和列号指定。
Value 在“数据交换”中详细介绍
Visual FoxPro API数据结构 </P><P>三、扩展程序库与Visual FoxPro环境的数据交换</P><P>  扩展程序库与Visual FoxPro环境的数据交换分两部分:程序库从Visual FoxPro接受参数;程序库返回值给Visual FoxPro。
1、扩展程序库从Visual FoxPro接受参数
  程序库中定义的函灵敏实际上只接受一个参数:一个指向参数块的指针。该参数块在ParamBlk结构中定义,保存了有关Visual FoxPro函数传递来的参数的全部信息。所以函数申明必须是如下格式:
void FunctionName(ParamBlk*parm)
ParamBlk结构定义包含在PRO_EXE.H中:
/*库函数的参数列表*/
typedef struct{
short int pCount:/*传递的参数个数*/
Paramneter[1]:/* pCount个参数*/
}ParamBlk;
  包含在ParamBlk结构中的parameter数据类型是一个含有一个Value结构和一个Locator结构的联合。当函数被Visual FoxPro调用时,可用这些结构来访问传递给它的参数。Parametet数据类型、Value结构和Locator结构都在PRO_EXT.H中定义:
/*给库函数的参数*/
typedefunion{
Value val;
Locator loc;
}Parameter
/*一个表达式的值*/
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;
/*一个表或内存变量的引用*/
typedef struct{
char 1_type;
short 1_where
l_NTI,
l_offset,
l_subs,
l_subl,l_sub2;
}Locator
  Visual FoxPro程序可按值或引用将变量传给库函数。默认时,内存变量的传递方式取决于SETUDFPARMS。其他变量(比如数组或字段)和表达通过值来传递。强制一个变量按引用传递,可在该变量引用之前加上@操作符。要强制一个变量按值传递,可把该变量用括号括起来。每个参数的信息保存在一个Value或者一个Locator结构中,按值的调用由value结构处理;按引用的调用则由Locator结构处理。下表说明了Value结构中各域与参数类型的对应关系:
数据类型 ev_type ev_width ev_length ev_long
ev_real ev_handle ev_currency
字符型 ‘C’ 字符串长度 字符串的
MHANDLE
数值型 `N' 显示宽度 小数位 双精度
整型 `I’ 显示宽度 长整型
日期型 `D' 日期
日期时间型 `T' 日期+(秒/86400.0)
货币型 `Y' 显示宽度 货币值
逻辑型 `L'
备注型 `M' FCHAN 0或1 备注字 备注字段编
段长度 移量
通用型 `G' FCHAN 备注字 备注字段编
段长度 移量
Null `O' 数据类型
下表说明了Locator结构中各域的含义:
结构元素 用法
l_type `R'
l_where -1表示内存变量,或为一工作区号
l_NTI 名称表索引
l_offset 字段偏移量
l_sub 0为内存变量,或为一下标数(如是数组)
l_sub1 第一下标(如果数组)
l_sub2 第二下标(如果维数组)
下面是接收参数的几个例子:
(1)接收一个数型参数
long long_var;
long_var=pann->P[0].Val.ev_long;
(2)接收一个日期型参数
double date;
date=parm->P[0]val.ev_real;
(3)通过传值方式接收一个字符串
char buf[256];
MHANDLE pvar;
pvar=parm->P[0]val.ev_handle;
_HLock(pvar); </P><P>_MemMove(buf,HandToPtr(pvar),parm->;
P[0].val.ev_length)
HUnlock(pvar)
为确保该字符串以‘\0’结尾,可令buf[255]=‘\0’;
(4)通过引用方式接收一个字符串
char buf[256];
Value val,*pval;
Locator *loc;
int errcode;
loc=&parm->p[0].loc;
pval=&val;
if(((errcode=_lode(loc,pvar))!=0);
_Error(-errcode);
//为确保以‘\0’结尾,要加1字节的空间
if (!_SetHandSize(pvar->ev_handle,pvar->
ev_length+1))
_Error(182)_;
//字符串尾加‘\0’
*((char*)_HandToPtr(pvar->ev_handle)+pvar->
ev_length)=`\0'
_HLock(pvar);
_MernMove(buf,_HandToPtr(pvar),pvar->
ev_length+1</P><P>
_HUnLock(pvar)
2、返回值给Visual FoxPro
返回值给Visual FoxPro,可以使用在PRO_EXT.H中说明的API函数;
函数说明
RetCHar(char*string) 返回一个以null终止的字符串。
_RetDateStr(char*string) 返回一个日期值。日期格式是mm/dd/yy[yy]。
_RetDateTimeStr(Char*string) 返回一个日期时间值。格式为mm/dd/yy[yy]hh:mm:ss。
_RetFloat(double flt int width int dec 返回一个浮点值。
_RetInt(longival int width) 返回一个整型值
_RetCurrency(CCY cval int width) 返回一个货币值。
_RetLogical(int flag) 返回一个逻辑值。0为“假”;非0为真。
_RetVal(Value*val) 传递一个完整的Visual FoxPro Value结构构;利用此函数,除备 注之外的任何Visual FoxPro数据类型都可返回。必须调用 _RetValo来返回一个包含内嵌null字符的字符串,或返回一个 NULL值。
  这些API函数十分好用,但有一个缺点;一个函数只能有一个返还信息。作为一个C语言程序员,对函数原型中形参的作用一定不陌生。究其根本,形参其实指示了一片内存区域,被调函数对该区域操作。函数结束后,信息保留在此内存区域,“返还”给主调函数。Visual FoxPro中按引用传递参数与之很相似。笔者根据此原理,成功的编写了几个引用返还信息的子程序。见示例;
(1)通过引用方式返回一个整型数
Locator*lo
Value temp
int errorcode
lo=&parm->p[0].loc
temp.ev_long=num//num
temp.ev_type=`I'
temp.ev_width=10;
if((errorcode=Stroe(lo,&temp))!=0
_Error(-errorcode)
(2)通过引用方式返回一个字符串
Locator*lo;
Vahue temp
int errcode
lo=&parm-P[0].loc
temp.ev_type=`C',
temp.ev_length=tength;//length为字符串长度
if((temp.ev_handle=_AllocHand(length)=0)
(Error(182)//内存不够
_Hlock(temp.ev_handle;//string为返回字符串指针
_MemMove(HandToPtr(temp.ev_handle)stringlength);
_HUnLock(temp.ev_handle);
if((errorcode=_store(lo,&temp))!=-
_Error(-errorcode)</P><P>  以上只介绍了编制Visual FoxPro扩展程序库的基本知识,读者如想处理自己的实际问题,还需要根据情况仔细分析。

网乐原科技

客服热线:0771-5761507

QQ:53290011

QQ邮箱:53290011@qq.com

工作时间:周一到周五 9:00-18:00

地址:广西南宁市江南万达写字楼C16栋1309室

物联网开发

关注我们

微信小商店 腾讯QQ客服 微信客服