VC DLL 动态链接库(一)

  首先我们来说说静态链接库

  静态数据库是指 lib 单独使用, 在编译时直接加入程序当中, 包含函数本身, 不仅包含头文件,还有源码, 称为静态链接库static link library。链接生成的程序可以独立运行。
 即lib文件是静态编译出来的,索引和实现都在其中。

  缺点是任何改动,都需要重新编译、链接,这个对大型的程序非常不便,升级也麻烦。有时,在更改数据结构时,需要重新编译整个工程,而非只编译、链接单个lib。

实现方法:

  在 VC new 一个名称为 libTest 的 static link library 工程, 并新建 lib.cpp 和 lib.h 两个文件,

// lib.h
#ifndef LIB_H
#define LIB_H
extern "C" int add(int x, int y);        // 声明为 C 编译、连接方式的外部函数
#endif
// lib.cpp
#include “lib.h”

int add(int x, int y){
    return x + y;
}

  编译这个工程就得到了一个 .lib 文件,这个文件就是一个函数库, 他提供了 add 的功能, 将头文件和 .lib 文件提交给用户后,用户可以直接使用其中的 add 函数了。

  下面来看看怎么使用这个库:

#include <iostream>
#include "lib.h"
#pragma comment(lib, "..\debug\libTest.lib")    // 指定与静态库一起连接

int main(){
    cout << add(2, 3) << endl;
    return 0;
}

  如果不用 #pragma comment 指定, 可以在设置->连接中添加 .lib 库。

  这个静态链接库让大概我们了解库是怎么一回事,下面我们来看看动态链接库

  动态链接库区别与静态链接库在于他是以 lib + dll 的方式实现,LIB 包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的 DLL 提供,称为动态链接库 dynamic link library。生成的程序需要dll配合使用。

  即 lib 一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容。应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。

  相比与静态链接库的优点在于:

  1.多个程序运行,共享一份代码。节省内存。

  2. 当 DLL 中的函数发生更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。

实现方法:

  在 VC 中 new 一个 Win32 Dynamic-Link Library 工程 dllTest, 并在工程中添加 lib.h 和 lib.cpp 文件,

// lib.h
#ifndef LIB_H
#define LIB_H
extern "C" int __declspes(dllexport)add(int a, int b);

#endif
// lib.cpp
#iclude "lib.h"

int add(int a, int b){
    return x + y;
}

下面看看如何使用这个动态链接库,与静态链接库又有哪些不同。

#include <iostream>
#include <windows.h>

typedef int(*lpAddFun)(int, int);

int main(){
    HINSTANCE hDll = NULL;
    lpAddFun addFun = NULL;
    hdll = LoadLibrary("..\Debug\lib.dll");
    if(hDll != NULL){
        addFun = (lpAddFun)GetProcAddress(hDll, "add");
        if(addFun != NULL){
            int result = addFun(2, 3);
            cout << result << endl;
        }
        FreeLibrary(hDll);
    }
    return 0;
}

  分析上面的代码, dllTest 工程中的 lib.cpp 文件与之前的静态链接库完全相同, 不同在于 lib.h 对于函数 add 的声明前面添加了 __declspes(dllexport) 语句,这个语句反的含义是声明函数 add 为 DLL 的函数。

  而 DLL 内的函数分为两种:

  1. DLL 导出函数, 可供应用程序调用

  2. DLL 内部函数, 只能在 DLL 程序使用, 应用程序无法调用他们

  

  而应用程序对这个 DLL 的调用和对静态链接库的调用却有较大差异, 下面我们来逐一分析

  首先,语句 typedef int(*lpAddFun)(int, int); 定义了一个与 add 函数接受参数类型和返回值均相同的函数指针类型

  随后, 在 main 函数中定义了 lpAddFun 的实例 addFun

  其次, 在 main 函数中定义了一个 DLL HINSTANCE 句柄实例 hDll, 通过 Win32 Api 函数 LoadLibrary 动态加载了 DLL 模块并将 DLL 模块句柄赋给了hDll

  再次, 在函数 main 中通过 Win32 Api 函数 GetProcAddress 得到了所加载 DLL 模块中函数 add 的地址并赋给了 addFun,经由函数指针 addFun 进行了对 DLL 中 add 函数的调用

  最后, 应用程序使用完 DLL 后, 在函数 main 中通过 Win32 Api 函数 FreeLibrary 释放了已经加载的 DLL 模块

  

  这就是 DLL 一些基本概念。

转载请注明出处:http://www.cnblogs.com/ygdblogs
原文地址:https://www.cnblogs.com/ygdblogs/p/5380686.html