VS2013下静态链接库(lib)和动态链接库(dll)的生成与使用
Posted Dufre.WC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VS2013下静态链接库(lib)和动态链接库(dll)的生成与使用相关的知识,希望对你有一定的参考价值。
前言
分享一下我使用的方法和遇到的问题,我先说方法,再说就我而言会出现的问题,最后说理论
以二分搜索生成库为例
静态链接库生成方法
1、新建一个项目,选择Win32项目
2、选择静态库,预编译头可以加也可以不加,这里我不加
如果没有选静态库,可以在项目/工程属性/配置属性/常规/项目默认值配置类型中修改
3、添加.cpp文件和.h文件
(1)demo.cpp文件
#include<iostream>
#include<vector>
#include"BinarySearchLib.h"
using namespace std;
//递归方法
int Binary_Search_Recursion(vector<int> v, int begin, int end, int key)
if (begin > end)
return -1;
int mid = (begin + end) >> 1;
if (v[mid] > key)
return Binary_Search_Recursion(v, begin, mid - 1, key);
else if (v[mid] < key)
return Binary_Search_Recursion(v, mid + 1, end, key);
else
return mid;
//非递归方法
int Binary_Search(vector<int> v, int begin, int end, int key)
if (begin > end)
return -1;
int mid = 0;
while (begin <= end)
mid = (begin + end) >> 1;
if (v[mid] > key)
end = mid - 1;
else if (v[mid] < key)
begin = mid + 1;
else
return mid;
return -1;
(2)BinarySearchLib.h文件
#ifndef _BinarySearchLib_H
#define _BinarySearchLib_H
#include<vector>
using namespace std;
int Binary_Search_Recursion(vector<int> v, int begin, int end, int key);
int Binary_Search(vector<int> v, int begin, int end, int key);
#endif
4、生成解决方案
这时候可以看到下方显示成功
5、把项目所在文件夹Debug文件夹下找到.lib文件
在这里我新建了一个控制台程序
(1)复制.lib和.h文件到需要使用项目的文件夹下
(2)把.h文件添加到工程中,并在工程中添加库#pragma comment(lib,"BinarySearchLib.lib")
如果不写#pragma comment(lib,"BinarySearchLib.lib")可以在项目/工程属性/链接器/输入/附加依赖项中添加BinarySearchLib.lib。
动态链接库生成方法
1、新建一个项目,选择Win32项目
2、选择DLL
如果没有选DLL,可以在项目/工程属性/配置属性/常规/项目默认值配置类型中修改
3、添加BinarySearchDll.h文件和BinarySearch.cpp文件
代码如下:(在静态库我用的是vector,但是显示调用的时候,得到的函数地址一直是0,不清楚原因,待究)
BinarySearchDll.h
#ifndef _MYCODE_H_
#define _MYCODE_H_
#ifdef DLLDEMO1_EXPORTS
#define EXPORTS_DEMO _declspec( dllexport )
#else
#define EXPORTS_DEMO _declspec(dllimport)
#endif
extern "C" EXPORTS_DEMO int Binary_Search(int v[], int begin, int end, int key);
#endif
BinarySearchDll.cpp
#include "stdafx.h"
#include "MyCode.h"
int Binary_Search(int v[], int begin, int end, int key)
if (begin > end)
return -1;
int mid = 0;
while (begin <= end)
mid = (begin + end) >> 1;
if (v[mid] > key)
end = mid - 1;
else if (v[mid] < key)
begin = mid + 1;
else
return mid;
return -1;
4、生成->生成解决方案
Debug目录下有BinarySearch.lib文件和BinarySearch.dll文件
5、调用动态链接库
有两种调用方式,静态(隐式)调用和动态(显式调用)
(1)静态(隐式)调用,和静态链接库方式一样
把.h文件和.lib文件放在需要调用的项目目录下,把.h文件添加到工程中,并在工程中添加库#pragma comment(lib,"BinarySearchLib.lib")如果不写可以在项目/工程属性/链接器/输入/附加依赖项中添加BinarySearchLib.lib。并把生成的.dll.要放到,使用该库的工程的 debug()目录下。
(2)动态(显式)调用
显式调用只需把dll文件放在被调用的项目Debug目录下
需要包含windows.h,动态调用法要用Windows API中的LoadLibrary()和GetProcAddress()来调入dll库,指出库中函数位置。
代码如下:
#include <windows.h>
#include <iostream>
using namespace std;
typedef int(*AddFunc)(int[], int, int, int);
int main(int argc, char *argv[])
int data[] = 1, 2, 3, 4, 5, 6, 7, 8 ;
HMODULE hDll = LoadLibrary("DLLDemo1.dll");
if (hDll != NULL)
AddFunc add = (AddFunc)GetProcAddress(hDll, "Binary_Search");
if (add != NULL)
cout << add(data, 0, 7, 3) << endl;
FreeLibrary(hDll);
可能会遇到的问题
1、上面已经说明,用vector不能调用,为什么?我还没解决
2、error C2664: “HMODULE LoadLibraryW(LPCWSTR)”: 无法将参数 1 从“const char [13]”转换为“LPCWSTR”
解决办法:项目->项目属性->配置属性->常规->字符集:选择使用多字节字符集
理论
(基本摘抄自博客)
1、.h .lib .dll文件关系
摘自:http://www.cnblogs.com/zcshan/archive/2010/12/03/1895605.html
.h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。
附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。
.h .lib .dll三者的关系是:
H文件作用是:声明函数接口
DLL文件作用是: 函数可执行代码
当我们在自己的程序中引用了一个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文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。在动态库的情况下,有两个文件,而一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。
2、C++静态链接库与动态链接库
摘自:http://www.cnblogs.com/skynet/p/3372855.html
库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。
所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤:
图:编译过程
(1)静态库
之所以成为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
试想一下,静态库与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结:
静态库对函数库的链接是放在编译时期完成的。
程序在运行时与函数库再无瓜葛,移植方便。
浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。
(2)动态库
通过上面的介绍发现静态库,容易使用和理解,也达到了代码复用的目的,那为什么还需要动态库呢?
为什么还需要动态库?
为什么需要动态库,其实也是静态库的特点导致。
1)空间浪费是静态库的一个问题。
2)另一个问题是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
动态库特点总结:
1)动态库把对一些库函数的链接载入推迟到程序运行的时期。
2)可以实现进程之间的资源共享。(因此动态库也称为共享库)
3)将一些程序升级变得简单。
4)甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。
Window与Linux执行文件格式不同,在创建动态库的时候有一些差异。
1)在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。
2)Linux下gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。
与创建静态库不同的是,不需要打包工具(ar、lib.exe),直接使用编译器即可创建动态库。
以上是关于VS2013下静态链接库(lib)和动态链接库(dll)的生成与使用的主要内容,如果未能解决你的问题,请参考以下文章