DLL and LIB

在StackOverflow中看到一个提问“what's the difference between DLL's and LIB's?”

有如下回复值得参考:

回复一:

回复二:

There are static libraries (LIB) and dynamic libraries (DLL).

Libraries are used because you may have code that you want to use in many programs. For example if you write a function that counts the number of characters in a string, that function will be useful in lots of programs. Once you get that function working correctly you don't want to have to recompile the code every time you use it, so you put the executable code for that function in a library, and the linker can extract and insert the compiled code into your program. Static libraries are sometimes called 'archives' for this reason.

Dynamic libraries take this one step further. It seems wasteful to have multiple copies of the library functions taking up space in each of the programs. Why can't they all share one copy of the function? This is what dynamic libraries are for. Rather then build the library code into your program when it is compiled, it can be mapped into your program as it is loaded into memory to run. Multiple programs running at the same time that use the same functions can all share one copy, saving memory. In fact, you can load dynamic libraries only as needed, depending on the path through your code. No point in having the printer routines taking up memory if you aren't doing any printing. On the other hand, this means you have to have a copy of the dynamic library installed on every machine your program runs on. This creates its own set of problems.

As an example, almost every program written in 'C' will need functions from a library called the 'C runtime library, though few programs will need all of the functions. The C runtime comes in both static and dynamic versions, so you can determine which version your program uses depending on particular needs.

回复三:

  • 我们先写个lib做个实验:

myLib.h:

#ifndef MYLIB_H
#define MYLIB_H
class myclass
{
public:
    myclass(){}
    ~myclass(){}
    void show();
};
#endif

mylib.cpp:

#include "mylib.h"
#include <iostream>
using namespace std;

void myclass::show()
{
    cout << "Hello Lib!" << endl;
}

不需要main函数就可以编译出lib文件:

然后写个例子来使用这个lib:

#include <iostream>

#include "..\..\..\testLib\testLib\testLib\mylib.h"

#pragma comment(lib,"testLib.lib")

int main()
{
    myclass mc;
    mc.show();
    system("pause");
    return 0;
}

include头文件和#pragma comment必不可少。运行结果:

别的工程要使用这个lib有两种方式:
(1)在工程选项-〉link-〉Object/Library Module中加入hello.lib
(2)可以在源代码中加入一行指令
#pragma comment(lib, "testLib.lib")
注意这个不是C++语言的一部分,而是编译器的预处理指令,用于通知编译器需要链接hello.lib。

这种lib文件的格式可以简单的介绍一下,它实际上是任意个obj文件的集合。obj文件则是cpp文件编译生成的,在本例中,lib文件只包含了一个 obj文件,如果有多个cpp文件则会编译生成多个obj文件,从而生成的lib文件中也包含了多个obj,注意,这里仅仅是集合而已,不涉及到 link,所以,在编译这种静态库工程时,你根本不会遇到链接错误。即使有错,错误也只会在使用这个lib的EXE或者DLL工程中暴露出来。第二个试验后,我们会介绍另一种lib。

  • 再写一个使用DLL的实验:
extern "C" __declspec(dllexport) void show()
{
    std::cout << "Hello DLL!" << std::endl;
}

声明为:

extern "C" __declspec(dllexport) void show();

这个DLL编译出来有如下文件:

此时生成的lib,不是obj文件的集合,即里面不含有实际的实现,它只是提供动态链接到DLL所需要的信息。这种lib可以在编译一个DLL工程时由编译器生成。

我们把DLL放在工程目录下,使用DLL中的show():

#include <iostream>

#include "..\..\..\_testDLL\testDLL\testDLL\testDLL.h"

#pragma comment(lib,"testDLL.lib")

int main()
{
    show();
    system("pause");
    return 0;
}

运行后:

如果不添加“#pragma comment(lib,"testDLL.lib") ”,就会报错:

如果把目录下的testDLL.dll删除,则会提示:

此时,lib与dll缺一不可;使用了DLL,但也必须用lib和头文件进行声明。

我们使用动态调用:

#include <iostream>
#include <windows.h>
typedef void(__cdecl *MYPROC)();
int main()
{
    HINSTANCE hInstLibrary = LoadLibrary("testDLL.dll");
    if (hInstLibrary != NULL)
    {
        MYPROC ProcShow = (MYPROC)GetProcAddress(hInstLibrary, "show");
        if (NULL != ProcShow)
        {
            ProcShow();
        }

    }
    system("pause");
    return 0;
}

运行结果:

  • 现在,来总结下DLL和Lib的区别与联系:

(1)lib是编译时需要的,dll是运行时需要的。 如果要完成源代码的编译,有lib就够了。 如果也使动态连接的程序运行起来,有dll就够了。

(2)一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中(即lib和dll都得用上)。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其 中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。

(3)在动态库的情况下,有两个文件,一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际 的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行时再把程序代码和被调用的函数代码链接起来,从而节省了内存资 源。从上面的说明可以看出,这种情况下,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。

  • 编写和使用DLL需要注意三个文件:

(1)dll头文件    
  它是指dll中说明输出的类或符号原型或数据结构的.h文件。当其它应用程序调用dll时,需要将该文件包含入应用程序的源文件中。    
(2)dll的引入库文件    
  它是dll在编译、链接成功后生成的文件。主要作用是当其它应用程序调用dll时,需要将该文件引入应用程序。否则,dll无法引入。exe在运行时,借助lib的指引,把需要用到的dll调用起来(需要用到的函数的实现存储在DLL中),如果仅仅是编译时,只用到lib中的索引(函数地址)即可。   

(3)dll文件(.dll)    
  它是应用程序调用dll运行时,真正的可执行文件。dll应用在编译、链接成功后,.dll文件即存在。开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,不必有.lib文件和dll头文件。   
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一 个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问 内存中单个 DLL 副本的内容。 

动态链接与静态链接的不同之处在于:动态链接允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。 

 

参考:http://www.cnblogs.com/devilmsg/articles/1266336.html

http://www.cppblog.com/amazon/archive/2009/09/04/95318.html

posted @ 2016-01-28 15:04  _No.47  阅读(397)  评论(0编辑  收藏  举报