VC++.NET中定义和使用MFC DLL
什么是dll?
dll指的是动态链接库(dynamic link library),它是一个可以被多个应用程序(甚至是不同语言编写的应用程序)同时调用的可执行二进制文件,是一个可共享的库。dll是建立在客户/服务器通信的概念上,包含若干函数、类或资源的库文件,函数和数据被存储在一个dll(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的dll。
在下面我们将通过一个具体的例子来说明如何利用vc.net定义一个dll文件,并且在vc.net的应用程序中调用,这个例子的主要功能是通过dll获取系统的机器名、操作系统类型和ip地址。
在vc.net中定义dll文件
选择vc.net菜单项,选择文件->新建->项目,在弹出的新建项目的对话框中,选择项目类型为visual c++ 项目,类别为mfc的工程,在右边的模板中,选择mfc dll模板,给项目取名为testdll,选择好项目的位置,按确定健,进入应用程序设置。
在应用程序设置中,我们可以看到,有三种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套接字,如果选择了这两项,程序会做一些初始化,在这里我们就不做讨论了。
在这个例子里,我们选择“使用共享的mfc dll”。
添加代码:
1、在工程中导入systeminfo.cpp和systeminfo.h文件,这两个文件用来获取本机的机器名,操作系统版本和本机ip列表,具体的定义,请参考源文件。
在testdll.h头文件中,引入systeminfo.h头文件
#include "systeminfo.h"
添加变量:
csysteminfo m_systeminfo;
2、在ctestdllapp类中添加三个函数用户获取信息:
//机器名
char* gethostname(void);
//系统类型
char* getsystemtype(void);
//ip地址
void getipaddresslist(char ** lpiplist,dword *lpnumber);
函数定义如下: //机器名
char* ctestdllapp::gethostname(void)
{
char* lpsz = new char[1024];
m_systeminfo.gethostname(lpsz);
return lpsz;
}
//系统类型
char* ctestdllapp::getsystemtype(void)
{
char* lpsz = new char[1024];
m_systeminfo.getlsystemtype(lpsz);
return lpsz;
}
//ip地址
void ctestdllapp::getipaddresslist(char ** lpiplist,dword *lpnumber)
{
m_systeminfo.getipaddresslist(lpiplist,lpnumber);
}
3、添加输出函数:
打开testdll工程中的“testdll.cpp”文件,在: // 唯一的一个 ctestdllapp 对象
ctestdllapp theapp;
的后面添加输出的dll函数,函数定义如下:
/******************* 在这里添加输出函数 ***************************/
/********************************************
函数名称:gethostname
功能:获取本机的机器名称
返回:strhostname-本机机器名称
*********************************************/
extern "c" _declspec(dllexport) void gethostname(lptstr strhostname )
{
//如果是传递字符串需要使用strcpy拷贝字符串的地址,而不能直接等于。
strcpy(strhostname,theapp.gethostname());
}
/********************************************
函数名称:getsystemtype
功能:获取本机操作系统版本
返回:strsystemtype-本机操作系统版本
*********************************************/
extern "c" _declspec(dllexport) void getsystemtype(char * strsystemtype)
{
strcpy(strsystemtype,theapp.getsystemtype());
}
/********************************************
函数名称:getipaddresslist
功能:获取本机的ip地址
返回:lpiplist-本机的ip地址数组,lpnumber ip地址个数
*********************************************/
extern "c" _declspec(dllexport) void getipaddresslist(char ** lpiplist,dword *lpnumber)
{
theapp.getipaddresslist(lpiplist,lpnumber);
}
最后编译工程文件,生成testdll.dll文件。
(文章来源 www.iocblog.net)
至此,一个dll文件已经做好了。
在vc.net中使用dll文件
新建一个基于对话框的vc.net工程demotestdll,界面如下图(运行结果图):
为了让demotestdll能够调用testdll.dll程序,需要让前者能够"看见" dll程序。我们将testdll.dll文件考到demotestdll的debug目录下,一个windows程序定位dll的次序是:
1、 包含exe文件的目录。
2、 进程的当前工作目录。
3、 windows系统目录。
4、 windows目录。
5、 列在path环境变量中的一系列目录。
在测试dll按钮添加下面代码: void cdemotestdlldlg::onbnclickedbutton1()
{
// todo: 在此添加控件通知处理程序代码
//声明dll函数
typedef void (_cdecl *gethostname)(lptstr strhostname);
typedef void (_cdecl *getsystemtype)(char * strsystemtype);
typedef void (_cdecl *getipaddresslist)(char ** lpiplist,dword *lpnumber);
//声明函数句柄
hmodule htestdll = null;
gethostname gethostname = null;
getsystemtype getsystemtype = null;
getipaddresslist getipaddresslist = null;
// 加载动态链接库
htestdll = loadlibrary("testdll.dll");
if(htestdll == null){
printf("cannot load lcddll.dll ");
exit(0);
}
/*** 找到每个函数的入口 ****/
//系统名称
gethostname = (gethostname)getprocaddress(htestdll,"gethostname");
if(gethostname==null)
{
printf("cannot load process gethostname ");
freelibrary(htestdll);
exit(1);
}
//操作系统类型
getsystemtype = (getsystemtype)getprocaddress(htestdll,"getsystemtype");
if(getsystemtype==null)
{
printf("cannot load process getsystemtype ");
freelibrary(htestdll);
exit(1);
}
//ip地址列表
getipaddresslist = (getipaddresslist)getprocaddress(htestdll,"getipaddresslist");
if(getsystemtype==null)
{
printf("cannot load process getipaddresslist ");
freelibrary(htestdll);
exit(1);
}
/*** 使用lptstr和使用char*定义的效果是一样的 ***/
//取机器名称
lptstr szhostname = new char[1024];
(*gethostname)(szhostname);
//取操作系统类型
char* szsystemtype = new char[1024];
(*getsystemtype)(szsystemtype);
//ip address list
dword iplistnumber = 0;
//声明方式一
//lptstr* lpaddress = new lptstr[256];
//声明方式二
char** lpaddress = new char*[256];
for(int i=0;i<256;i++)
{
lpaddress[i] = null;
}
(*getipaddresslist)(lpaddress,&iplistnumber);
//显示在界面
m_sethostname.setwindowtext(szhostname);
m_setsystemtype.setwindowtext(szsystemtype);
//将ip添加到list 中
for(int i=0;i {
m_iplist.addstring(lpaddress[i]);
}
}
Tag: MFC ,动态链接库
文章整理:iocblog
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。