【笔记】刚到公司,初识dll

    刚到公司,发了一个本子一支笔一个文件夹(VC++深入详解、C++ Primer、Effective C++、Effective STL)。

    废话不多说,第一项任务:熟悉VS,联系创建dll文件,并从中导出函数供应用程序使用。

 

一、简介一下dll

    DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数、变量或类。通常不能直接运行,也不能接收消息。它们是一些独立的文件,只有当其他模块调用dll中的函数时,才发挥作用。

    Windows API 中所有的函数都包含在dll中,有三个最重要的:

    1、Kernel32.dll:包含用于管理内存、进程和线程的函数。

    2、User32.dll:包含用于执行用户界面任务的函数。

    3、GDI32.dll:包含哪些用于画图和显示文本的函数。

    【静态库】

    函数和数据被编译进一个二进制文件(.lib)。编译连接时,复制这些函数和数据,把它们和应用程序的其它模块组合起来,创建最终的可执行文件(.exe)。发布产品时只需发布可执行文件,不需要发布静态库。

   【动态库】

    动态库往往提供两个文件:

    引入库文件(.lib)——包含导出的函数和变量的符号名。

    DLL文件(.dll)——包含该DLL实际的函数和数据。

    编译链接时不复制,运行时才加载(将DLL映射到进程的地址空间中),然后访问导出函数。发布产品时除了可执行文件,还要有动态链接库。

 

二、从dll中导出函数(采用隐式加载dll)

1、新建一个dll,在dll.cpp中写两个简单的函数:

   int add(int a, int b)

   {  return a + b;

   }

   int subtract(int a,int b)

   {  return a = b;

   }

   点击生成dll,则会在debug目录下产生11个文件,其中包含.lib和.dll文件。

2、在想要导出的函数前,加上导出标志符:_declspec(dllexport)。如下:

   _declspec(dllexport) int add(int a,int b)    {  return a+b;    }    _declspec(dllexport)int subtract(int a,int b)    {  return a-b;    }

3、创建一个基于对话框的应用程序test.exe。

   //在testDlg.cpp中声明函数    extern int add(int a,int b);    extern int subtract(int a,int b);

  //接着实现两个按钮的消息映射函数

   void CtestDlg::OnBnClickedBtnAdd()   {     OnBtnAdd();//手动添加   }

   void CtestDlg::OnBnClickedBtnSubtract()   {      OnBtnSubtract();//手动添加   }

   void CtestDlg::OnBtnAdd(void)   {      CString str;      str.Format("5 + 3 = %d",add(5,3));      MessageBox(str);

  }

   void CtestDlg::OnBtnSubtract(void) {      CString str;      str.Format("5 - 3 = %d",subtract(5,3));      MessageBox(str);

  } 4、编译一下,出现三个错!没有载入dll......

   将刚才生成的.lib和.dll两个文件复制到test所在目录下。

   编译还是错!没有设置库......

   在项目--属性--链接器--输入--附加依赖项--填写“dll.lib”

   再次生成exe就好啦!

 

三、从dll中到处类(采用隐式加载dll)

先注明一点:不是导出就一定能够使用该类,仍旧受限于类本身的访问权限!

1、在dll.h中写一个类,并添加导出标志符:    class  _declspec(dllexport) Point   {     public:        void output(int x,int y);   };   在dll.cpp中实现:

  void Point::output(int x,int y)   {     //返回调用者进程当前正在使用的那个窗口的句柄       HWND hwnd = ::GetForegroundWindow();    //获取DC       HDC hdc = ::GetDC(hwnd);       char buf[20];       memset(buf,0,20);       sprintf(buf,"x = %d,y = %d",x,y);    //输出坐标       ::TextOut(hdc,0,0,buf,strlen(buf));    //释放DC      ::ReleaseDC(hwnd,hdc);

  }    因为用到库函数,所以在dll.cpp中包含头文件:

   #include "Windows.h"    #include "stdio.h" 2、在test.cpp中使用这个类:

   void CtestDlg::OnBtnOutput(void)   {      Point pt;      pt.output(5,3);

   }

  当然,也要包含定义类的头文件:

   #include "dll.h" 3、将.lib和.h文件放在test目录下,将.dll文件放在test\debug目录下。

4、编译生成exe,完成。

 

【使用宏定义】

1、在dll.h文件中添加一个宏:

   #ifdef AAAA

   #define DLL_API _declspec(dllexport)

   #else

   #define DLL_API _declspec(dllimport)

   #endif

 

   则定义类如下:

   class  DLL_API Point    {      public:        void output(int x,int y);    };

2、在stdafx.h中:#define AAAA

(dll.cpp包含了stdafx.h所以就是export啦!testDlg.cpp中没有定义,所以就是impoort!)

 

 

 

 参考资料:VC++深入详解——孙鑫

 

 

 

 

 

posted @ 2012-03-21 16:40  醪糟汤圆  Views(509)  Comments(0Edit  收藏  举报