欢迎访问 Lu程序设计

Lu扩展动态库

往Lu中添加常量、函数或其他任意类型的数据是非常方便的。为了便于函数和数据共享，常将函数和数据封装到动态库中，以动态库的形式向Lu添加，这种动态库称Lu扩展动态库。Lu扩展动态库只需要一个输出函数：

//Lu扩展动态库唯一的输出函数；
//hLu：Lu32.dll的句柄；iInit!=0：初始化动态库，iInit=0：释放动态库；
//me：指向任意数据的指针，可用于验证用户能否使用该库，为了方便验证，约定该指针指向一个wchar_t类型的字符串。
//iInit!=0时，返回值LuDll=0：初始化失败；LuDll=1：初始化成功；返回值LuDll=2：初始化成功，仅注册一些常量，初始化完成后可卸载该库。
//iInit=0时，返回值LuDll=0：释放失败；LuDll=1：释放成功；
extern "C" int _stdcall LuDll32(HINSTANCE hLu,int iInit,void *me)
{
.
.
.
if(iInit) //初始化动态库
{
.
.
.
return 1;
}
else //释放动态库
{
.
.
.
return 1;
}
}

可以看出，虽然Lu扩展动态库只有一个输出函数，但该函数接受了主调程序加载的Lu32.dll的句柄，因而可以完成任意复杂的功能。为了应用程序的安全性，在Lu扩展动态库中禁止使用InitLu(初始化Lu)和FreeLu(释放Lu)这两个函数。

设计商业性Lu扩展动态库时，在初始化过程中要验证me，看宿主程序提供的字符串形式的注册码是否符合要求，若符合要求，商业库可提供全部功能，否则仅提供部分功能或禁止使用该库。

如果在动态库中启动了另一线程，要注意多线程程序中使用Lu函数的原则，即：除了GetRunErr()、TestRunErr()和SetRunErr()三个函数外，其余的函数只能在单线程中使用（不允许两个及两个以上的线程同时运行这些函数）。为此，约定用pUseLu=SearchKey("UseLu",5,luPriKey_User); 获得一个函数指针进行多线程之间互斥使用Lu的通讯，该函数可在主程序或Lu扩展动态库中定义，函数说明如下：

//（1）iUse=1时，表示要申请使用Lu，若函数返回值 UseLu=0：申请成功；UseLu=1：申请不成功，
//其他线程正在使用Lu，稍后再进行申请；UseLu=-1：申请不成功，表示应用程序要释放Lu，
//因此要做好退出前的准备工作。
//（2）iUse=2时，表示要申请使用Lu，如果其他线程正在使用Lu，函数不返回，进行等待，直至申请成功。
//若函数返回值 UseLu=0：申请成功；UseLu=1：申请不成功，线程本身正在使用Lu，不能重复进行申请；
//UseLu=-1：申请不成功，表示应用程序要释放Lu，因此要做好退出前的准备工作。
//（3）iUse=0时，表示要归还Lu的使用权，函数返回值无意义。
//（4）iUse=3时，设置安全标志，表示Lu运行正常，函数返回值无意义。 一般在二级函数中设置该标志，当该函
//数在较长时间内运行时，可用此标志通知Lu，此时的运行是正常的，没有陷入无限循环等情况。
//（5）iUse=4时，取消安全标志，表示Lu运行处于不可控制阶段（有陷入无限循环的可能），函数返回值无意义。
//（6）iUse=5时，查询安全标志，UseLu=0：运行正常；UseLu=1：运行情况无法预测（有陷入无限循环的可
//能），这是Lu运行的一般情况。
//注意1：Lu是极为重要而有限的资源，用完后要及时归还。
//注意2：UseLu(1)（或者UseLu(2)）和UseLu(0)必须成对使用。注意不能在二级函数中使用该功能，
//因为二级函数本身就是在Lu工作区中运行的。
//注意3：UseLu(3)和 UseLu(4)也要成对使用，且一般在二级函数中使用该功能。
extern "C" int _stdcall UseLu(int iUse);

在主调程序或任一个Lu扩展动态库中均可以设置一个函数void _stdcall LuMessage(wchar_t *)。然后将该函数的地址用InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v)传送给Lu。约定所有Lu扩展动态库都使用该函数发送信息。任一线程均可根据需要设置该函数。

在设计Lu扩展动态库时，要采用二级函数命名空间方式（例如："Fun2Space::FunName"）输出函数，以尽量避免函数重名。

在设计Lu扩展动态库时，要遵循谁注册函数和数据谁释放的原则。

在加载和卸载Lu扩展动态库时，要遵循先进后出的原则，即先加载的后进行卸载。

可以用C/C++、delphi、FORTRAN等任一种高级语言设计Lu扩展动态库。

例子：该例子定义了两个函数和一个常量：Add(1,2)、Add(1.0,2.0)用于计算两个整数或实数的和；Sub(1,2)、Sub(1.0,2.0)用于计算两个整数或实数的差；常量pi=3.1416。

模块定义文件：

    ; DllExample.def : Declares the module parameters for the DLL.

    LIBRARY      "DllExample"

    EXPORTS
        ; Explicit exports can go here

    LuDll32		@1

DllExample.CPP文件：

    #include "windows.h"
    #include "lu32.h"

    //保存Lu32.dll的句柄
    HINSTANCE hLu;

    //保存Lu32.dll中的输出函数地址
    luSetFunction pSetFunction;
    luSetConst pSetConst;
    luDeleteKey pDeleteKey;

    ///////////////////////////////////////////////////////

    //定义可由Lu调用的二级函数（外部函数）
    LuData _stdcall lu_Add(luINT ,LuData *,void *);
    LuData _stdcall lu_Sub(luINT ,LuData *,void *);

    wchar_t *FunName[]={L"Add",L"Sub",L""};	//二级函数名
    luINT FunPara[]={1,1};			//-2表示有不确定的多个自变量，-1表示有0个自变量，0表示有1个自变量，1表示有2个自变量
    LuData (_stdcall *FunCal[])(luINT ,LuData *,void *)={lu_Add,lu_Sub}; //二级函数指针数组
    bool FunReg[2];				//记录是否在Lu注册了

    ///////////////////////////////////////////////////////

    //Lu动态库唯一的输出函数
    //iInit!=0时，进行初始化。LuDll32=0：初始化失败；LuDll32=1：初始化成功；LuDll32=2：初始化成功，仅注册一些常量，初始化完成后可卸载该库。
    //iInit=0时，LuDll32=0：释放失败；LuDll32=1：释放成功。
    extern "C" int _stdcall LuDll32(HINSTANCE hLU,int iInit,void *me)
    {
    	int i;

    	if(iInit)	//初始化动态库
    	{
    		hLu=hLU;
    		pSetFunction=(luSetFunction) GetProcAddress(hLu,"SetFunction");
    		pSetConst=(luSetConst) GetProcAddress(hLu,"SetConst");
    		pDeleteKey=(luDeleteKey) GetProcAddress(hLu,"DeleteKey");

    		//注册二级函数
    		for(i=0;FunName[i][0];i++)
    		{
    			FunReg[i]=pSetFunction(FunName[i],FunCal[i],FunPara[i])?false:true;
    			if(!FunReg[i]) MessageBox(NULL,FunName[i],L"DllExample 注册函数失败！",32);
    		}

    		//注册常量
    		LuData a;
    		a.BType=luStaData_double; a.VType=luStaData_double; *(double *)&(a.x)=3.1416;
    		pSetConst(L"pi",&a);

    		return 1;
    	}
    	else	//释放动态库
    	{
    		//注销二级函数
    		for(i=0;FunName[i][0];i++)
    		{
    			if(FunReg[i]) pDeleteKey((char *)FunName[i],wcslen(FunName[i])*2,luKey_Function,NULL,0);
    		}

    		//注销常量
    		pDeleteKey((char *)L"pi",4,luKey_Const,NULL,0);

    		return 1;
    	}
    }

    ////////////////////////////////////////////////////二级函数定义

    LuData _stdcall lu_Add(luINT mm,LuData *xx,void *vFor)	//两个数相加
    {
    	LuData a;

    	if(xx->VType==luStaData_int64 && (xx+1)->VType==luStaData_int64)
    	{
    		a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=xx->x+(xx+1)->x;
    	}
    	else if(xx->VType==luStaData_double && (xx+1)->VType==luStaData_double)
    	{
    		a.BType=luStaData_double; a.VType=luStaData_double; *(double *)&(a.x)=*(double *)&(xx->x)+*(double *)&((xx+1)->x);
    	}
    	else
    	{
    		a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
    	}
    	return a;
    }

    LuData _stdcall lu_Sub(luINT mm,LuData *xx,void *vFor)	//两个数相减
    {
    	LuData a;

    	if(xx->VType==luStaData_int64 && (xx+1)->VType==luStaData_int64)
    	{
    		a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=xx->x-(xx+1)->x;
    	}
    	else if(xx->VType==luStaData_double && (xx+1)->VType==luStaData_double)
    	{
    		a.BType=luStaData_double; a.VType=luStaData_double; *(double *)&(a.x)=*(double *)&(xx->x)-*(double *)&((xx+1)->x);
    	}
    	else
    	{
    		a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
    	}
    	return a;
    }

版权所有© Lu程序设计 2011-2011，保留所有权利
E-mail: forcal@sina.com QQ：630715621
最近更新: 2011年11月03日