首先,我们先来看看什么是库?
库:函数库是实现了某一类功能的若干的函数和数据二进制代码的集合。
注意:库中虽然是函数的二进制代码集合,但不能独立执行,可以被载入内存,和其他程序结合起来执行。
Windows 静态库:xxx.lib
动态库:xxx.dll
Linux 静态库:xxx.a
动态库:xxx.so
我们这里所说的静态库和动态库指的是链接时刻不同。首先,我们来回忆一下编译的流程,我们让普通程序编译成可执行程序的步骤:预处理——编译——汇编——链接
其实前3个步骤是我们的基本C语言代码都需要运行的,生成xxx.o文件,最终向三个方向发展=>可执行文件、静态库或动态库。
一、静态库
静态库之所以叫静态库,是因为我们在编译的阶段,就把我们函数库的代码载入可执行文件中。由于整个函数库的所有数据都会被整合进目标代码中,那么它的优缺点就显而易见了。
优点:就是编译后的执行程序不需要外部的函数库支持。
缺点:就是生成的文件比较大,若是函数库的代码改变了,则需要重新编译。
特点:静态库的代码在编译过程中已经被载入可执行程序,因此生成的可执行程序体积较大。
下面介绍使用VS2008制作和调用静态库:
1.工程的建立——选择Win32项目,输入工程名
在应用程序设置中选择“静态库”选项
这样就完成了工程的创建。
2.添加两个文件,一个为lib.cpp,另一个为头文件lib.h。我们所编写的函数放在lib.cpp,而其原型放在lib.h。这两个文件的内容为:
- //lib.cpp
- #include "stdafx.h"
- #include "lib.h"
- int add(int x,int y)
- {
- return x + y;
- }
- //lib.h
- #ifndef LIB_H
- #define LIB_H
- extern "C" int add(int x,int y);
- #endif
编译后,根据编译配置类型,可以在Release或Debug文件夹下即可查看编译后的结果。
3.下面看如何使用这个函数,新建一个控制台应用程序,并将“lib.h”以及生成后的“win32_Lib.lib”复制至新建工程的源文件夹下,再编写测试应用源程序如下:
- //test_Lib.cpp:定义控制台应用程序的入口点
- #include <stdio.h>
- #include "lib.h"//函数原型声明
- #pragma comment(lib,"win32_Lib.lib");//将静态库导入
- int main()
- {
- printf("2+3 = %d",add(2,3));
- getchar();
- return 0;
- }
#pragma comment(lib,"win32_Lib.lib");表示链接win32_Lib.lib这个库。和在工程设置里写上链入win32_Lib.lib的效果是一样的,不过这种方法写的程序,别人在使用你的代码的时候,就不用再设置工程settings了
二、动态库
顾名思义,根据名字你就知道,我们动态库肯定是动态链接的。没错,我们的动态函数库在编译的时候并没有被编译进目标代码中,而是在运行的时候,才来链接我们函数库中要用到的函数。因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库,以及库路径。
特点:动态库的代码在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此可执行代码体积小。
下面介绍使用VS2008制作和调用动态库:
1.工程的建立——选择Win32项目,输入工程名win32_Dll
在应用程序设置中选择“静态库”选项
这样就完成了工程的创建。
2.添加两个文件,一个为win32_Dll.cpp,另一个为头文件win32_Dll.h。我们所编写的函数放在win32_Dll.cpp,而其原型放在win32_Dll.h。这两个文件的内容为:
- // win32_Dll.cpp : 定义 DLL 应用程序的导出函数。
- #include "stdafx.h"
- #include "win32_Dll.h"
- #define EXPORTING_DLL
- int add(int x,int y)
- {
- return x + y;
- }
- //win32_Dll.h
- #ifndef WIN32_DLL_H
- #define WIN32_DLL_H
- #ifdef EXPORTING_DLL
- #define API_TYPE __declspec(dllexport)
- #else
- #define API_TYPE __declspec(dllimport)
- #endif
- extern "C" int API_TYPE add(int x,int y);
- #endif
编译后,根据编译配置类型,可以在Release或Debug文件夹下即可查看编译后的结果。
3.下面看如何使用这个函数,新建一个控制台应用程序,并将生成后的“win32_Dll.dll”和“win32_Dll.lib”复制至新建工程的源文件夹下,再编写测试应用源程序如下:
- #include <Windows.h>
- #include <stdio.h>
- typedef int (*lpAddFun)(int,int);//函数指针
- int main()
- {
- HINSTANCE hDll;
- lpAddFun addFun;
- hDll = LoadLibrary("win32_Dll.dll");//加载动态库
- if(hDll)
- {
- addFun = (lpAddFun)GetProcAddress(hDll,"add");
- if (addFun)
- {
- printf("2 + 3 = %d\n",addFun(2,3));
- }
- }
- getchar();
- FreeLibrary(hDll);//卸载动态库
- return 0;
- }
LoadLibray()函数载入指定的动态链接库,并将它映射到当前进程使用的地址空间,一旦载入,即可访问库内保存的资源;
GetProcAddress()寒山寺检索指定的动态链接库(DLL)中输出库函数地址,如果函数调用成功,返回值是DLL中输出函数地址,失败,返回值是NULL。