欢迎访问 Lu程序设计
C/C++使用Lu脚本字符串键树
1 说明
要演示本文的例子,你必须下载Lu32脚本系统。本文的例子需要lu32.dll、lu32.lib、C格式的头文件lu32.h,相信你会找到并正确使用这几个文件。
用C/C++编译器创建一个控制台应用程序,复制本文的例子代码直接编译运行即可。
2 关于Lu字符串键树
参考Lu编程指南,在Lu中,表达式、常量、函数、任意自定义数据等等,所有的东西都放到一棵键树中。Lu键树保存数据的格式如下(数据与键的名称、长度、类型是一一对应的关系):
KeyStr:键的名称(char *KeyStr)。区分大小写,可包含任意字符,包括NULL('\0')。
ByteNum:键的长度(luINT ByteNum)。ByteNum>0。
KeyType:键的类型(luKEY KeyType)。
键的类型KeyType有两种:公有键(KeyType>=luPubKey_User)和私有健(KeyType<=luPriKey_User)。
Lu所支持的程序可能很复杂,程序可以动态加载许多功能模块,每一个模块都可以向Lu键树注册数据,若注册为公有键,则该键可以被任意的功能模块所删除;若注册为私有健,则只有自己可以删除该键。
键的类型可以用函数LockKey加锁。锁定键的类型后,该键只能存储一种数据类型。如果没有锁定键的类型,则该键可以存储任意多种类型的数据。
公有键luPubKey_User和私有健luPriKey_User用来存放一些约定的键,不能加锁。例如,核心库约定使用如下函数输出信息:
typedef void (_stdcall * luMessage) (wchar_t *); //显示Lu信息的函数指针
主程序或其他模块,需设计如下输出信息的函数:
void _stdcall LuMessage(wchar_t *pWStr) //输出Lu信息,该函数注册到Lu,由Lu及二级函数调用
{
... ...
}
然后将该函数用InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v)注册到Lu(注意,使用的是公有键luPubKey_User)。约定Lu及所有二级函数都使用该函数显示信息。任一线程均可根据需要设置该函数。查询该函数的方法为:
luMessage pMessage=(luMessage)SearchKey("\0\0\0\0",4,luPubKey_User);
Lu键的类型如表1所示。
表1 Lu键的类型
类别 | 键的类型 | 标识符 | 生成对象 | 查询对象 | 销毁对象 | 说明 | ||
系统键 | 255~-199 | 系统使用。 | ||||||
-128~-255 | -200 | luPriKey_UserSearch | 用户可查询和删除的私有健最大值 | 键的类型由系统定义,但用户可以使用。键的类型均被锁定。都是动态数据类型,即系统定义的动态数据类型。 | ||||
-252 | luDynData_realarray | NewSysObj | SearchKey/GetArray | DeleteKey | 动态64位实数数组 | |||
-253 | luDynData_intarray | NewSysObj | SearchKey/GetArray | DeleteKey | 动态64位整数数组 | |||
-254 | luDynData_string | NewSysObj | SearchKey/GetStr | DeleteKey | 动态字符串 | |||
-255 | luDynData_lu | NewSysObj | SearchKey | DeleteKey | 动态Lu数据 | |||
用户键 | 256 | luPubKey_User | InsertKey/GetBufObj | SearchKey | DeleteKey | 公有键。用来存放一些约定的键。不能加锁。 | ||
-256 | luPriKey_User | InsertKey/GetBufObj | SearchKey | DeleteKey | 私有键。用来存放一些约定的键。不能加锁。 | |||
> 256 | > luPubKey_User | InsertKey/GetBufObj | SearchKey | DeleteKey | 由用户定义的公有键。均大于256。可加锁。 | |||
< -256 | < luPriKey_User | InsertKey/GetBufObj | SearchKey | DeleteKey | 由用户定义的私有键。均小于-256。可加锁。 | |||
-1073741824 | luPoiKey_User | InsertKey/GetBufObj | SearchKey | DeleteKey | 指针键最小值。小于luPoiKey_User的非指针键只有自己可以销毁。指针键不仅要求键的类型KeyType>=luPoiKey_User,而且要求用InsertKey插入键时键的长度为4,但一定要取-1。 |
如果用C/C++设计一个较大的程序,该程序允许加载许多来自不同的人用不同的语言设计的模块,Lu键树对私有数据的保护功能将会大有用武之地。
虽然Lu键树是为Lu脚本系统设计的,但实际上Lu键树可用单独使用。本例C/C++使用Lu键树管理数据的例子,并没有使用Lu脚本表达式(函数)的编译运算功能。
本文的例子中,代码1演示了公有键(KeyType>=luPubKey_User)的用法;代码2演示了指针型私有键(KeyType>=luPoiKey_User)的用法;代码3演示了非指针型私有键(KeyType<luPoiKey_User)的用法。
3 代码
代码1:演示公有键
#include <stdio.h>
#include <malloc.h>
#include "lu32.h"
#pragma comment( lib, "lu32.lib" )
int kkk; //为避免编译器优化而设置
typedef struct pub_k //将注册为公有键
{
int k;
} pub_k;
void _stdcall Del_pub_k(void *me) //销毁pub_k的函数
{
free(me);
}
typedef struct pub_d //将注册为公有键
{
double d;
} pub_d;
void _stdcall Del_pub_d(void *me) //销毁pub_d的函数
{
kkk=0; //避免编译器将Del_pub_d和Del_pub_k优化为同一个函数
free(me);
}
LuData _stdcall OpLock_pub_d(luINT m,LuData *Para,void *hFor,int theOperator) //pub_d的运算符重载函数
{
LuData a;
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0; //不对pub_d类型的对象做运算,总返回nil
return a;
}
#define key_no_lock luPubKey_User+10 //不对该公有键加锁
#define key_lock luPubKey_User+20 //将对该公有键加锁
void main(void)
{
pub_k *pk;
pub_d *pd;
void *NowKey=NULL; //为避免编译器发出警告进行初始化,实际上不需要
if(!InitLu()) return; //初始化Lu
pk=(pub_k *)malloc(sizeof(pub_k));
pk->k=10;
pd=(pub_d *)malloc(sizeof(pub_d));
pd->d=1.23;
InsertKey("my_k",4,key_no_lock,pk,Del_pub_k,NULL,1,NowKey); //在Lu键树中注册键值
InsertKey("my_d",4,key_no_lock,pd,Del_pub_d,NULL,1,NowKey); //在Lu键树中注册键值
pk=(pub_k *)SearchKey("my_k",4,key_no_lock); //在Lu键树中查找键值
if(pk) printf("%d\n",pk->k);
pd=(pub_d *)SearchKey("my_d",4,key_no_lock); //在Lu键树中查找键值
if(pd) printf("%f\n",pd->d);
DeleteKey("my_k",4,key_no_lock,NULL,0); //在Lu键树中删除键值
DeleteKey("my_d",4,key_no_lock,NULL,0); //在Lu键树中删除键值
pk=(pub_k *)SearchKey("my_k",4,key_no_lock); //在Lu键树中查找键值
if(!pk) printf("my_k 已销毁!\n");
pd=(pub_d *)SearchKey("my_d",4,key_no_lock); //在Lu键树中查找键值
if(!pd) printf("my_d 已销毁!\n");
LockKey(key_lock,Del_pub_d,OpLock_pub_d); //在Lu键树中加锁键,只能存储pub_d类型
pk=(pub_k *)malloc(sizeof(pub_k));
pk->k=20;
pd=(pub_d *)malloc(sizeof(pub_d));
pd->d=5.67;
InsertKey("my_k",4,key_lock,pk,Del_pub_k,NULL,1,NowKey);//在Lu键树中注册pub_k类型键值,失败
InsertKey("my_d",4,key_lock,pd,Del_pub_d,NULL,1,NowKey);//在Lu键树中注册pub_d类型键值,成功
pk=(pub_k *)SearchKey("my_k",4,key_lock); //在Lu键树中查找键值,失败
if(pk)
printf("%d\n",pk->k);
else
printf("没有找到 my_k!\n");
pd=(pub_d *)SearchKey("my_d",4,key_lock); //在Lu键树中查找键值,成功
if(pd) printf("%f\n",pd->d);
DeleteKey("my_k",4,key_lock,NULL,0); //在Lu键树中删除键值,失败
DeleteKey("my_d",4,key_lock,NULL,0); //在Lu键树中删除键值,成功
pd=(pub_d *)SearchKey("my_d",4,key_lock); //在Lu键树中查找键值
if(!pd) printf("my_d 已销毁!\n");
FreeLu(); //释放Lu
}
运行结果:
10
1.230000
my_k 已销毁!
my_d 已销毁!
没有找到 my_k!
5.670000
my_d 已销毁!
代码2:演示指针型私有键
#include <stdio.h>
#include <malloc.h>
#include "lu32.h"
#pragma comment( lib, "lu32.lib" )
typedef struct pri_k //将注册为私有键
{
int k;
} pri_k;
void _stdcall Del_pri_k(void *me) //销毁pri_k的函数
{
free(me);
}
LuData _stdcall OpLock_pri_k(luINT m,LuData *Para,void *hFor,int theOperator) //pri_k的运算符重载函数
{
LuData a;
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0; //不对pri_k类型的对象做运算,总返回nil
return a;
}
#define key_lock (luPriKey_User-20) //将对该私有键加锁
#define imax 10 //私有键值最大数
void main(void)
{
pri_k *pk[imax],*p_k;
int i;
luKEY ByteNum;
void *NowKey=NULL; //为避免编译器发出警告进行初始化,实际上不需要
if(!InitLu()) return; //初始化Lu
LockKey(key_lock,Del_pri_k,OpLock_pri_k); //在Lu键树中加锁键,只能存储pri_k类型
for(i=0;i<imax;i++)
{
pk[i]=(pri_k *)malloc(sizeof(pri_k));
pk[i]->k=100+i;
ByteNum= i%2 ? -1 : sizeof(luVOID); //i为偶数时注册为指针键,否则注册为非指针键
InsertKey((char *)&(pk[i]),ByteNum,key_lock,pk[i],Del_pri_k,NULL,1,NowKey); //在Lu键树中注册键值
}
printf("--- 保存在Lu键树中的数据!---\n\n");
for(i=0;i<imax;i++)
{
p_k=(pri_k *)SearchKey((char *)&(pk[i]),sizeof(luVOID),key_lock); //在Lu键树中查找键值
if(p_k) printf("%d\n",p_k->k);
}
printf("\n--- 删除约1/3数据!---\n\n");
for(i=0;i<imax/3;i++)
{
DeleteKey((char *)&(pk[i]),sizeof(luVOID),key_lock,Del_pri_k,0); //在Lu键树中删除键值
}
for(i=0;i<imax;i++)
{
p_k=(pri_k *)SearchKey((char *)&(pk[i]),sizeof(luVOID),key_lock); //在Lu键树中查找键值
if(p_k)
printf("%d\n",p_k->k);
else
printf("没有找到第 %d 个数据!\n",i);
}
printf("\n--- 运行垃圾收集器后数据!---\n\n");
GC(0); //垃圾收集
for(i=0;i<imax;i++)
{
p_k=(pri_k *)SearchKey((char *)&(pk[i]),sizeof(luVOID),key_lock); //在Lu键树中查找键值
if(p_k)
printf("%d\n",p_k->k);
else
printf("没有找到第 %d 个数据!\n",i);
}
printf("\n--- 解锁键并全部销毁数据!---\n\n");
LockKey(key_lock,NULL,OpLock_pri_k); //在Lu键树中解锁键
for(i=0;i<imax;i++)
{
p_k=(pri_k *)SearchKey((char *)&(pk[i]),sizeof(luVOID),key_lock); //在Lu键树中查找键值
if(p_k)
printf("%d\n",p_k->k);
else
printf("没有找到第 %d 个数据!\n",i);
}
FreeLu(); //释放Lu
}
运行结果:
--- 保存在Lu键树中的数据!---
100
101
102
103
104
105
106
107
108
109
--- 删除约1/3数据!---
没有找到第 0 个数据!
没有找到第 1 个数据!
没有找到第 2 个数据!
103
104
105
106
107
108
109
--- 运行垃圾收集器后数据!---
没有找到第 0 个数据!
没有找到第 1 个数据!
没有找到第 2 个数据!
没有找到第 3 个数据!
104
没有找到第 5 个数据!
106
没有找到第 7 个数据!
108
没有找到第 9 个数据!
--- 解锁键并全部销毁数据!---
没有找到第 0 个数据!
没有找到第 1 个数据!
没有找到第 2 个数据!
没有找到第 3 个数据!
没有找到第 4 个数据!
没有找到第 5 个数据!
没有找到第 6 个数据!
没有找到第 7 个数据!
没有找到第 8 个数据!
没有找到第 9 个数据!
代码3:演示非指针型私有键
将代码2中的
#define key_lock (luPriKey_User-20) //将对该私有键加锁
改为:
#define key_lock (luPoiKey_User-20) //将对该私有键加锁
然后编译运行即可。
运行结果:
--- 保存在Lu键树中的数据!---
100
102
104
106
108
--- 删除约1/3数据!---
没有找到第 0 个数据!
没有找到第 1 个数据!
没有找到第 2 个数据!
没有找到第 3 个数据!
104
没有找到第 5 个数据!
106
没有找到第 7 个数据!
108
没有找到第 9 个数据!
--- 运行垃圾收集器后数据!---
没有找到第 0 个数据!
没有找到第 1 个数据!
没有找到第 2 个数据!
没有找到第 3 个数据!
104
没有找到第 5 个数据!
106
没有找到第 7 个数据!
108
没有找到第 9 个数据!
--- 解锁键并全部销毁数据!---
没有找到第 0 个数据!
没有找到第 1 个数据!
没有找到第 2 个数据!
没有找到第 3 个数据!
没有找到第 4 个数据!
没有找到第 5 个数据!
没有找到第 6 个数据!
没有找到第 7 个数据!
没有找到第 8 个数据!
没有找到第 9 个数据!
4 函数说明
本例用到了Lu的7个输出函数:初始化Lu的函数InitLu,释放Lu的函数FreeLu,插入键值的函数InsertKey,查找键值函数SearchKey,删除键值的函数DeleteKey,加锁键函数LockKey,垃圾收集器函数GC。从这里查看这些函数的说明:Lu编程指南。
5 难点分析
代码1演示了公有键的用法。(1)如果公有键没有加锁,可以存储若干种数据类型,如果进行了加锁,只能存储一种数据类型;(2)可以删除一个不存在的键而没有副作用;(3)删除键值时不需要提供删除函数,故谁都可以销毁公有键;(4)没有对InsertKey、SearchKey、DeleteKey、LockKey的返回值做全面检查,但不影响演示效果。
代码2演示了指针型私有键的用法。(1)程序先对私有键key_lock进行加锁,然后注册了10个对象,一半注册为指针键,一半注册为非指针键;(2)Lu脚本的垃圾收集器运行时,会回收指针键,但对非指针键没有影响;(3)键解锁时会自动销毁该类键型的所有数据。
代码3演示了非指针型私有键的用法。(1)程序试图注册指针键,但失败了;(2)Lu脚本的垃圾收集器运行时,对非指针键没有影响。
代码中在加锁一个键时,用到了运算符重载函数,在此先略过,以后会专门讨论该函数。
6 其他
你可能注意到了,我的联系方式就在下面,如有不明之处或有什么建议,可随时与我进行联系。
版权所有© Lu程序设计 2002-2013,保留所有权利
E-mail: forcal@sina.com QQ:630715621
最近更新: 2014年01月02日