十五、动态链接库介绍以及静态库的编写

来源:互联网 发布:君智咨询 知乎 编辑:程序博客网 时间:2024/05/16 23:33

1.   静态库和动态库的区别:

       a. 函数库:将一些公用函数制作成函数库供其它程序调用;

       b. 静态库:编译的时候将整个静态库都加入工程的链接(即将静态库中的函数复制到主程序中),生成的.exe文件包含库中函数的全部定义;

       c. 动态库:链接时不将库包含进工程,形成的.exe当然也不包含库中函数的定义,链接时只在工程中保留库的入口(即库在硬盘中的位置),运行.exe时动态加载库函数;

       d. 注意:链接了静态库的程序,直接在程序内部就包含了库中函数的定义,因此加载程序的同时也将库函数一并加载,而链接动态库的程序只有在执行到调用库函数的语句时才从硬盘上找.dll将里面的函数进行加载;

       e. 由此可见动态库的特点:

            i.   首先也是一种可执行程序,也是经过编译链接后形成的;

            ii.  但是不能独立运行,依赖于其它程序对其的调用;

            iii. 也就是说动态库是其它程序的一部分,调用它的程序时主程序;

            iv. 动态库和主程序之间的关系就是,动态库向主程序输出函数,而主程序抽调动态库的函数;

       f.  动态库的优点:

            i.   减少程序的空间;

            ii.  充分利用资源,节省空间(多个程序可以调用一个动态库);

            iii. 可以用任何语言编写,因为dll规定过统一标准的接口,这可以充分发挥人力资源,简化项目管理;

       h. 两种库文件在Windows操作系统中的表示:

            i.   静态库:其后缀为.lib,即library的缩写;

            ii.  动态库:由两个文件组成,一部分是.dll文件(即dynamic link library的缩写),另一部分也是.lib文件,但是和静态库文件的.lib不同,动态库中的.lib叫做"引入库文件",.dll中包含了导出函数的定义的二进制码,而.lib文件中包含的是.dll中的函数以及变量的符号声明(即函数和变量的入口);

            iii. 动态库的链接有两种方式,一种是隐式一种是显示,在使用隐式链接时只需要将引入库文件和主程序链接就行了;


2.   编写一个简单的静态链接库:

       a. 创建一个工程,名称定为Test,工程类型选择Static Library(即静态链接库);

       b. 在step 1 of 1中将预编译和MFC支持都选择;

       c. 编写Test.h以及Test.cpp并生成.lib文件:

//Test.h#ifndef _STA_LIB_#define _STA_LIB_extern "C" void StaticFunction();//extern表示作用范围为文件外//由于库中函数都是要导出的,因此必须声明成extern的//"C"表示导出库中函数时使用C语言的改名规则,但是该规则不能导出类的成员函数//因为对于不同的C++编译器其改名规则都是不同的//但是所有C++编译器都使用相同的CFront//因此使用C语言的改名规则不会导致程序中命名混乱//命名混乱会导致链接报错#endif//Test.cpp//任何一个.cpp文件都必须包含该预编译文件//否则链接时将发生错误#include "StdAfx.h"#include "Test.h"void StaticFunction(){AfxMessageBox("这是一个静态库中的函数!");}

       

3.   建立一个简单的单文档MFC程序作为主程序调用上例创建的静态库:

       a. 在菜单栏中建立一个名为”静态库“的项目,在其子菜单中添加名为”调用静态库函数“的项,ID就叫IDM_CALL_STATIC;

       b. 为其建立一个WM_COMMAND消息响应函数,并在该函数定义的.cpp文件中包含静态库的.h文件(作为对静态库中函数的引入,也就是说静态库的.h文件就相当于动态库的.lib引入库文件);

       c. 需要将.lib文件和.h文件拷贝到MFC工程的目录中;

       d. 消息响应函数的实现(包括包含头文件并和静态库建立链接的语句):

//一定要包含引入库文件//静态库的引入库文件就相当于.h文件#include "Test.h"//即声明该文件将链接一个静态库(即第一个参数lib)//并且链接的静态库名为Test.lib//如果没有将.h和.lib文件拷贝到当前目录下  //则需要将它们俩的完整路径名交代清楚#pragma comment(lib, "Test.lib")void CTest_MFCView::OnStaticCall() {// TODO: Add your command handler code hereStaticFunction();}