关于VS2013下制作和使用静态库和动态库

引言

  • 什么是库:库是写好的现有的,成熟的,可以复用的代码。
  • 所谓静态、动态是指链接。将一个程序编译成可执行程序的步骤:

静态库在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。

为什么还需要动态库?

  • 空间浪费是静态库的一个问题。
  • 另一个问题是静态库对程序的更新、部署带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。
  • 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才会载入,也解决了静态库对程序的更新、部署带来麻烦。用户只需要更新动态库即可,增量更新。

静态库

动态库

VS2013下新建静态库

第一步:新建一个静态库(static library)项目

第二步:编写项目内容

首先在头文件下添加一个头文件static.h

头文件static.h的内容如下:

int sum(int a, int b);//声明函数

在源文件下添加一个源文件static.cpp,内容如下:

#include "static.h"
#include "stdafx.h"
int sum(int x, int y){
return x + y;}

第三步:生成.lib文件

在菜单栏选择“生成”->“生成解决方案”就可以了。

然后打开工程文件夹,在Debug目录下(编译选择的是默认的Debug和Win32)就可以看到一个和项目名称相同的lib文件:

这样供给别人调用的lib文件就生成好了,下面讲如何调用这个静态库文件。

第四步:调用.lib文件

首先新建另外的项目TestCallLib1,这个项目将使用我们刚刚生成的静态库

将头文件static.h和静态库TestLib1.lib拷到TestCallLib1\TestCallLib1目录下

首先将主函数写好

有两种方法调用静态库:

1、右键“目录”“属性”选择“链接器”->“输入”,在“附加依赖项”这里添加要调用的lib文件的名字:TestLib1.lib。

2、或者编写代码为

运行得到结果!

动态库的制作

创建动态库关键是导出函数,DLL中导出函数的声明有两种方式:

  • 一种方式是:在函数声明中加上__declspec(dllexport);
  • 另外一种方式是:采用模块定义(.def)文件声明,(.def)文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。

1、采用模块定义(.def)文件声明

新建项目win32,应用程序类型选择dll

需要自己手动添加四个文件

头文件dllgenerator.h,内容:

int Add(int, int);int Mul(int, int);

函数定义文件dllgenerator.cpp,内容:

int Add(int a, int b){return a + b;}
int Mul(int c, int d){return c * d;}

dllmain.cpp : 定义 DLL 应用程序的入口点

// dllmain.cpp : 定义 DLL 应用程序的入口点。

#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

需包含库<windows.h>,里面有很多与生成动态库的相关函数和参数

建立源文件Source.def(划重点)

在此文件第一行引号中填你的项目名称即可,EXPORTS下面列出要生成的函数名称 格式:“名称 @序号”)

LIBRARY "TestDll1"
EXPORTS
Add @1
Mul @2

点击菜单栏 生成 -> 生成解决方案,我们的动态库就生成成功了

2、通过关键字导出函数

新建项目过程同上!这里的关键是头文件中需要加入关键字__declspec(dllexport),这个关键字是导出函数的关键!

添加lib.h和lib.cpp函数

生成后同样看见.dll文件和.lib文件

动态库的加载——静态加载

新建项目DLLTestor,将刚刚生成的.dll、.lib、.h文件拷贝到DLLTestor\DLLTestor文件下( .lib、.h 文件不是必须拷入的,我这里并没有拷入)

工程调用dll时首先在工程文件目录中查找dll,找不到后在C:\Windows\System32 中找。所以我们自己项目简单调用dll时就把生成的dll文件复制到工程目录中,如果经常用可以把dll文件放到C:\Windows\System32中

调用动态库是调用 .dll、 .lib、 .h 三个文件

编好代码并设置.lib和.h文件的调用路径

右键“目录”“属性”选择“链接器”->“输入”,在“附加依赖项”这里添加要调用的lib文件的名字:TestDll1.lib

运行得到结果

动态加载和静态加载

动态加载是指在生成可执行文件时不将所有程序用到的函数链接到一个文件,因为有许多函数在操作系统带的dll文件中,当程序运行时直接从操作系统中找。

而静态加载就是把所有用到的函数全部链接到exe文件中。动态加载是只建立一个引用的接口,而真正的代码和数据存放在另外的可执行模块中,在运行时再装入;

而静态加载是把所有的代码和数据都复制到本模块中,运行时就不再需要库了。

动态加载

#include "stdafx.h"
#include "dllgenerator.h"
#include "windows.h"
int _tmain(int argc, CHAR* argv[]){
printf("Hello World!\n");
HMODULE hmod = LoadLibrary("TestDll1.dll"); //  //用于加载dll
typedef int(*LoadProc)(int x, int y);
LoadProc Load_proc = (LoadProc)GetProcAddress(hmod, "Add");
//GetProcAddress()用于获得函数地址
int iRet = Load_proc(3, 5); //得到地址后调用该函数,返回较大值
printf("the Add the value is:%x\n", iRet);
return 0;
}

需要理解调用动态库主要用到三个函数,加载LoadLibrary、调用GetProcAddress、释放FreeLibrary!

别忘了在右键“目录”“属性”选择“链接器”->“输入”,在“附加依赖项”这里添加要调用的lib文件的名字:TestDll1.lib

大家在制作过程中可能会遇到如下的问题

这是字符集的问题,具体的解决方案是:右键项目->属性

把字符集从unicode改成多字节字符集。

h头文件 .lib库文件 .dll动态链接库文件关系

  • .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。

    附加依赖项添加的是.lib而不是.dll,若生成了DLL,则肯定也生成了LIB文件。
  • H文件的作用:声明函数接口
  • DLL文件作用:函数可执行代码
  • LIB文件作用:当我们在自己的程序中引用了一个H文件里的函数,链接器怎么知道该调用哪个DLL文件呢?这就是LIB文件的作用了。它告诉链接器调用的函数在哪个DLL中,函数执行代码在DLL中的什么位置,这也就是为什么需要附加依赖项.LIB文件,它起到桥梁的作用。
  • 如果是生成静态库文件,则没有DLL,只有lib,这时函数可执行代码部分也在lib文件中。

再说一点

目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。

关于VS2013下制作和使用静态库和动态库的更多相关文章

  1. Linux下C++静态库、动态库的制作与使用

    参考博文:C++静态库与动态库 >> 静态库 1. 静态库的制作 a) 编辑 name.cpp 和name.h文件 b) $g++ -c name.cpp //注意带参数-c,否则直接编译 ...

  2. linux系统环境下的静态库和动态库的制作

    linux系统下的应用编程需要系统提供的库文件,包括静态库或动态库.不管是静态库还是动态库,都是编译好的二进制文件.在我们编译程序时要链接的目标文件,静态库是链接的时候直接编译到程序里,和程序成为一体 ...

  3. Linux下制作和使用静态库和动态库

    概述 Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库.linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib. 静态函数库: 这类库的名字一般是libxxx. ...

  4. Linux下Gcc生成和使用静态库和动态库详解(转)

    一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...

  5. Linux下Gcc生成和使用静态库和动态库详解

    参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...

  6. [转]Linux下用gcc/g++生成静态库和动态库(Z)

    Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10|  分类: linux |  标签:链接库  linux  g++  gcc  |举报|字号 订阅     ...

  7. Linux库函数制作(静态库、动态库)

    Linux库函数制作(静态库.动态库) 静态库与动态库 链接方式 链接分为两种:静态链接.动态链接 静态链接: 由链接器在链接时将库的内容加入到可执行程序中 静态链接的特点是: 优点: 对运行环境的依 ...

  8. 【转】Linux下gcc生成和使用静态库和动态库详解

    一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不 ...

  9. Windows下静态库与动态库的创建与使用

    Windows下静态库与动态库的创建与使用 学习内容:本博客介绍了Windows下使用Visual C++ 6.0制作与使用静态库与动态库的方法. --------CONTENTS-------- 一 ...

随机推荐

  1. unity3d射线控制移动

    看看效果图 代码: using UnityEngine; using System.Collections; public class T2 : MonoBehaviour { // Use this ...

  2. git 语法

    $ git init  // 初始化一个Git仓库 会生成一个.git目录 $ git status   // 查看仓库的状态 $ git add .   // 将所有修改添加到暂存区 $git ad ...

  3. Koa中设置中文Cookie值

    默认情况下, 如果 ctx.cookies.set('user', '杨过', { domain: 'xxxx', path: 'xxxx', maxAge: 24 * 60 * 60 * 1000, ...

  4. Python全栈-day2-day3-语法基础1

    1.什么是变量,为什么需要变量 变量即变化的量,衡量现实中实物的状态:程序执行的本质就是一系列的状态变化,变是程序本身执行的直接体现,因此程序的执行需要这种机制将执行状态以及状态的变化保存下来. 1) ...

  5. Yii2 Restful api分页

  6. npm 代理的设置和取消

    管理员权限下的控制台输入: 设置代理 npm config set proxy=http://127.0.0.1:8080 npm config set registry=http://registr ...

  7. 通用技术 mysql 亿级数据优化

    通用技术 mysql 亿级数据优化 一定要正确设计索引 一定要避免SQL语句全表扫描,所以SQL一定要走索引(如:一切的 > < != 等等之类的写法都会导致全表扫描) 一定要避免 lim ...

  8. window下安装cross-env解决NODE_ENV ts-node 不是内部或外部命令,也不是可运行的程序 或批处理文件 问题

    window下安装cross-env解决NODE_ENV ts-node 不是内部或外部命令,也不是可运行的程序 或批处理文件 问题 在git bash上启动无法进行调试,采用cross-env后可以 ...

  9. AtCoder Beginner Contest 045 C - たくさんの数式 / Many Formulas

    Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement You are given a string ...

  10. 基于jquery 的dateRangePicker 和 My97DatePicker

    引入相应的date插件 <script type="text/javascript" src="../plugins/daterangepicker/moment. ...