VC++.NET中定义和使用MFC DLL

分类: VC.NET   出处:iocblog整理  更新时间:2008-06-06   添加到收藏  

  什么是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
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。