静态库:在链接步骤中,连接器将从库文件中取得所需的代码,复制到生成的可执行文件中,这种库成为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。即静态库中的指令都全部被直接包含在最终生成的EXE文件中了。
动态库:动态链接库是一个包含可由多个程序同时使用的代码和数据库,DLL不是可执行文件。动态连接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
那么静态链接库和动态链接库中的lib有什么区别呢?
静态库中的lib:该LIB包含函数代码本身(即包括函数的索引,也包括实现),在编译时直接将代码加入程序当中
动态库中的lib:该LIB包含了函数所在DLL文件和文件中函数位置的信息(索引),函数实现代码由运行时加载在进程空间中的DLL提供
总之,lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接库的程序运行起来,只需要dll。
//以上转自他处
接下来演示几种DLL的编写和使用的情况
1、新建项目 mathdll(供其它程序使用的动态库程序),分别加入头文件mathdll.h和源文件mathdll.cpp
mathdll.h
#ifndef MATHDLL_H
#define MATHDLL_H
#ifdef WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
extern DLL_EXPORT int mathAdd(int a, int b);
#endif
mathdll.cpp
#include "mathdll.h"
int mathAdd(int a, int b)
{
return(a + b);
}
编译后会生成一个DLL文件和一个LIB文件分别是:mathdll.dll 和 mathdll.lib
接下来创建一个调用程序mathTest,包含源文件mathTest.cpp
mathTest.cpp
#include <iostream>
#include "mathdll.h"
using std::cout;
#pragma comment(lib, "mathdll.lib")
int main(int argc, char* argv[])
{
cout << "the sum of 1 and 2 is "<<mathAdd(1, 2);
getchar();
return 0;
}
将DLL文件放在文件当前目录,就可以正确运行程序,运行结果为
2、假设将动态库项目中的.h文件移出项目,并将.cpp文件改成
#ifdef WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
int DLL_EXPORT mathAdd(int a, int b)
{
return(a + b);
}
这时,我们并没有这个库的头文件,这时我们就必须知道cpp文件中的函数,将调用程序改成如下面即可:
#include <iostream>
//#include "mathdll.h"
using std::cout;
#pragma comment(lib, "mathdll.lib")
extern int mathAdd(int a, int b);
int main(int argc, char* argv[])
{
cout << "the sum of 1 and 2 is "<<mathAdd(1, 2);
getchar();
return 0;
}
这样程序还是能够成功编译并运行。
3、接下来,我们将动态库项目中的.cpp文件改成如下:
#ifdef WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
extern "C" DLL_EXPORT int mathAdd(int a, int b)
{
return(a + b);
}
重新编译后,更换调用程序的库文件。重新编译调用程序,会出现如下错误:
1>ClCompile:
1> mathTest.cpp
1>mathTest.obj : error LNK2019: 无法解析的外部符号 "int __cdecl mathAdd(int,int)" (?mathAdd@@YAHHH@Z),该符号在函数 _main 中被引用
1>C:\Users\Administrator\Documents\Visual Studio 2010\Projects\mathTest\Debug\mathTest.exe : fatal error LNK1120: 1 个无法解析的外部命令
1>
1>生成失败。
为何会产生这种情况?原因是在第三方库中mathAdd这个函数是通过C的方式编写的,而调用它的确实C++程序。在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等.而在C中,只是简单的函数名字而已,不会加入其他的信息.也就是说:C++和C对产生的函数名字的处理是不一样的。所以只要对调用程序作如下修改就能解决这个问题:
#include <iostream>
//#include "mathdll.h"
using std::cout;
#pragma comment(lib, "mathdll.lib")
extern "C" int mathAdd(int a, int b);
int main(int argc, char* argv[])
{
cout << "the sum of 1 and 2 is "<<mathAdd(1, 2);
getchar();
return 0;
}