什么是DLL?
DLL指的是动态链接库(DynamicLinkLibrary),它是一个可以被多个应用程序(甚至是不同语言编写的应用程序)同时调用的可执行二进制文件,是一个可共享的库。DLL是建立在客户/服务器通信的概念上,包含若干函数、类或资源的库文件,函数和数据被存储在一个DLL(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的DLL。
在下面我们将通过一个具体的例子来说明如何利用VC.Net定义一个DLL文件,并且在VC.Net的应用程序中调用,这个例子的主要功能是通过DLL获取系统的机器名、操作系统类型和IP地址。
在VC.Net中定义DLL文件
选择VC.Net菜单项,选择文件->新建->项目,在弹出的新建项目的对话框中,选择项目类型为VisualC项目,类别为MFC的工程,在右边的模板中,选择MFCDLL模板,给项目取名为TestDLL,选择好项目的位置,按确定健,进入应用程序设置。 财,软联盟,fs119.net
在应用程序设置中,我们可以看到,有三种DLL类型,它们依次对应着三类DLL。
静态DLL与共享DLL的区别是:前者使用的是MFC的静态链接库,生成的DLL文件长度大,一般不使用这种方式,后者使用MFC的动态链接库,生成的DLL文件长度小;动态链接到MFC的共享DLL所有输出的函数应该以如下语句开始(用于正确切换MFC模块状态):AFX_MANAGE_STATE(AfxGetStaticModuleState())扩展DLL用来建立MFC的派生类,只被用MFC类库所编写的应用程序调用。常规DLL(包括静态与动态)的一个特点是在源文件里有一个继承CWinApp的类(从CWinApp派生,但没有消息循环),被导出的函数是C类或者C成员函数,调用常规DLL的应用程序不必一定是MFC应用程序。扩展DLL和常规DLL不一样,它没有一个从CWinApp继承而来的类的对象,编译器默认了一个DLL入口函数DLLMain()作为对DLL的初始化。
另外还可以添加两个附加功能:自动化和windows套接字,如果选择了这两项,程序会做一些初始化,在这里我们就不做讨论了。
在这个例子里,我们选择“使用共享的MFCDLL”。
添加代码:
1、在工程中导入systeminfo.cpp和systeminfo.h文件,这两个文件用来获取本机的机器名,操作系统版本和本机IP列表,具体的定义,请参考源文件。
在TestDLL.h头文件中,引入systemInfo.h头文件
#include"systemInfo.h"
添加变量:
CSystemInfom_SystemInfo;
2、在CTestDLLApp类中添加三个函数用户获取信息:
程序代码:
//机器名
char*GetHostName(void);
//系统类型
char*GetSystemType(void);
//IP地址
voidGetIPAddressList(char**lpIPList,DWORD*lpNumber);
函数定义如下:
DLL指的是动态链接库(DynamicLinkLibrary),它是一个可以被多个应用程序(甚至是不同语言编写的应用程序)同时调用的可执行二进制文件,是一个可共享的库。DLL是建立在客户/服务器通信的概念上,包含若干函数、类或资源的库文件,函数和数据被存储在一个DLL(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的DLL。
在下面我们将通过一个具体的例子来说明如何利用VC.Net定义一个DLL文件,并且在VC.Net的应用程序中调用,这个例子的主要功能是通过DLL获取系统的机器名、操作系统类型和IP地址。
在VC.Net中定义DLL文件
选择VC.Net菜单项,选择文件->新建->项目,在弹出的新建项目的对话框中,选择项目类型为VisualC项目,类别为MFC的工程,在右边的模板中,选择MFCDLL模板,给项目取名为TestDLL,选择好项目的位置,按确定健,进入应用程序设置。 财,软联盟,fs119.net
在应用程序设置中,我们可以看到,有三种DLL类型,它们依次对应着三类DLL。
静态DLL与共享DLL的区别是:前者使用的是MFC的静态链接库,生成的DLL文件长度大,一般不使用这种方式,后者使用MFC的动态链接库,生成的DLL文件长度小;动态链接到MFC的共享DLL所有输出的函数应该以如下语句开始(用于正确切换MFC模块状态):AFX_MANAGE_STATE(AfxGetStaticModuleState())扩展DLL用来建立MFC的派生类,只被用MFC类库所编写的应用程序调用。常规DLL(包括静态与动态)的一个特点是在源文件里有一个继承CWinApp的类(从CWinApp派生,但没有消息循环),被导出的函数是C类或者C成员函数,调用常规DLL的应用程序不必一定是MFC应用程序。扩展DLL和常规DLL不一样,它没有一个从CWinApp继承而来的类的对象,编译器默认了一个DLL入口函数DLLMain()作为对DLL的初始化。
财.软联盟.fs119.net
另外还可以添加两个附加功能:自动化和windows套接字,如果选择了这两项,程序会做一些初始化,在这里我们就不做讨论了。
在这个例子里,我们选择“使用共享的MFCDLL”。
添加代码:
1、在工程中导入systeminfo.cpp和systeminfo.h文件,这两个文件用来获取本机的机器名,操作系统版本和本机IP列表,具体的定义,请参考源文件。
在TestDLL.h头文件中,引入systemInfo.h头文件
#include"systemInfo.h"
添加变量:
CSystemInfom_SystemInfo;
2、在CTestDLLApp类中添加三个函数用户获取信息:
//机器名
char*GetHostName(void);
//系统类型
char*GetSystemType(void);
//IP地址
voidGetIPAddressList(char**lpIPList,DWORD*lpNumber);
//机器名
char*CTestDLLApp::GetHostName(void)
{
char*lpsz=newchar[1024];
m_SystemInfo.GetHostName(lpsz);
returnlpsz;
}
//系统类型
char*CTestDLLApp::GetSystemType(void)
{
char*lpsz=newchar[1024];
m_SystemInfo.GetlSystemType(lpsz);
returnlpsz;
}
//IP地址
voidCTestDLLApp::GetIPAddressList(char**lpIPList,DWORD*lpNumber)
{
m_SystemInfo.GetIPAddressList(lpIPList,lpNumber);
}
打开TestDLL工程中的“TestDLL.cpp”文件,在://唯一的一个CTestDLLApp对象
CTestDLLApptheApp;
的后面添加输出的DLL函数,函数定义如下:
/*******************在这里添加输出函数***************************/
/********************************************
函数名称:GetHostName
功能:获取本机的机器名称
返回:strHostName-本机机器名称
*********************************************/
财软联盟 fs119.net
extern"C"_declspec(dllexport)voidGetHostName(LPTSTRstrHostName)
{
//如果是传递字符串需要使用strcpy拷贝字符串的地址,而不能直接等于。
strcpy(strHostName,theApp.GetHostName());
}
/********************************************
函数名称:GetSystemType
功能:获取本机操作系统版本
返回:strSystemType-本机操作系统版本
*********************************************/
extern"C"_declspec(dllexport)voidGetSystemType(char*strSystemType)
{
strcpy(strSystemType,theApp.GetSystemType());
}
/********************************************
函数名称:GetIPAddressList
功能:获取本机的IP地址
返回:lpIPList-本机的IP地址数组,lpNumberIP地址个数
*********************************************/
extern"C"_declspec(dllexport)voidGetIPAddressList(char**lpIPList,DWORD*lpNumber)
{
theApp.GetIPAddressList(lpIPList,lpNumber);
}
最后编译工程文件,生成TestDLL.dll文件。
至此,一个DLL文件已经做好了。 财管.家园.fs119.net
财.管家园.fs119.net
财软联.盟.fs119.net
财管家园.fs119.net
财管家园.fs119.net 在VC.Net中使用DLL文件
新建一个基于对话框的VC.Net工程DemoTestDLL,界面如下图(运行结果图):
财,软联盟,fs119.net
为了让DemoTestDLL能够调用TestDLL.dll程序,需要让前者能够"看见"DLL程序。我们将TestDLL.dll文件考到DemoTestDLL的Debug目录下,一个Windows程序定位DLL的次序是:
1、包含EXE文件的目录。
2、进程的当前工作目录。
3、Windows系统目录。
4、Windows目录。
5、列在Path环境变量中的一系列目录。
在测试DLL按钮添加下面代码: 财软,联盟,fs119.net
voidCDemoTestDLLDlg::OnBnClickedButton1()
{
//TODO:在此添加控件通知处理程序代码
//声明DLL函数
typedefvoid(_cdecl*GETHOSTNAME)(LPTSTRstrHostName);
typedefvoid(_cdecl*GETSYSTEMTYPE)(char*strSystemType);
typedefvoid(_cdecl*GETIPADDRESSLIST)(char**lpIPList,DWORD*lpNumber);
//声明函数句柄
HMODULEhTestDLL=NULL;
GETHOSTNAMEGetHostName=NULL;
GETSYSTEMTYPEGetSystemType=NULL;
GETIPADDRESSLISTGetIpAddressList=NULL;
//加载动态链接库
hTestDLL=LoadLibrary("TestDLL.dll");
if(hTestDLL==NULL)\
{
printf("cannotloadLCDDLL.dll\n");
exit(0);
}
/***找到每个函数的入口****/
//系统名称
GetHostName=(GETHOSTNAME)GetProcAddress(hTestDLL,"GetHostName");
if(GetHostName==NULL)
{
printf("cannotloadprocessGetHostName\n");
FreeLibrary(hTestDLL);
exit(1);
}
//操作系统类型
GetSystemType=(GETSYSTEMTYPE)GetProcAddress(hTestDLL,"GetSystemType"); 财管家园,fs119.net
if(GetSystemType==NULL)
{
printf("cannotloadprocessGetSystemType\n");
FreeLibrary(hTestDLL);
exit(1);
}
//IP地址列表
GetIpAddressList=(GETIPADDRESSLIST)GetProcAddress(hTestDLL,"GetIPAddressList");
if(GetSystemType==NULL)
{
printf("cannotloadprocessGetIpAddressList\n");
FreeLibrary(hTestDLL);
exit(1);
}
/***使用LPTSTR和使用char*定义的效果是一样的***/
//取机器名称
LPTSTRszHostName=newchar[1024];
(*GetHostName)(szHostName);
//取操作系统类型
char*szSystemType=newchar[1024];
(*GetSystemType)(szSystemType);
//IPAddressList
DWORDipListNumber=0;
//声明方式一
//LPTSTR*lpAddress=newLPTSTR[256];
//声明方式二
char**lpAddress=newchar*[256];
for(inti=0;i<256;i)
{
lpAddress[i]=NULL;
}
(*GetIpAddressList)(lpAddress,&ipListNumber);
//显示在界面
m_setHostName.SetWindowText(szHostName);
m_setSystemType.SetWindowText(szSystemType);
//将IP添加到list中
财管家园.fs119.net
for(inti=0;i<ipListNumber;i)
{
m_IPList.AddString(lpAddress[i]);
}
}