lib文件和dll文件
一. 简介
1.1 C++两种库文件
- lib包含了函数所在的dll文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的dll提供,称为动态链接库dynamic link library。(这种方式更灵活,写的程序体积小,但是需要.exe和dll同时发布)
- lib包含函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库static link library。(这种方式不是很灵活,因为lib被编译到.exe中,写出的程序体积大,但是只需要发布exe即可,不需要dll文件)
1.2 C++两种链接方式
- 动态链接使用动态链接库,允许可执行模块(.dll文件或.exe文件)仅包含在运行时定位 dll 函数的可执行代码所需的信息。
- 静态链接使用静态链接库,链接器从静态链接库 lib 获取所有被引用函数,并将库同代码一起放到可执行文件中。
1.3 lib与dll的区别
1. 功能区别
- lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
- 如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
- 动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。
2. 文件数量的区别
- (静态连接)使用lib需注意两个文件:
- .h头文件,包含lib中说明输出的类或符号原型或数据结构。应用程序调用lib时,需要将该文件包含入应用程序的源文件中。
- .LIB文件,略。
- (动态连接)使用dll需注意三个文件:
- .h头文件,包含dll中说明输出的类或符号原型或数据结构的.h文件。应用程序调用dll时,需要将该文件包含入应用程序的源文件中。
- .LIB文件,是dll在编译、链接成功之后生成的文件,作用是当其他应用程序调用dll时,需要将该文件引入应用程序,否则产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32API函数LoadLibrary、GetProcAddress装载。
- .dll文件,真正的可执行文件,开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,并不需要.lib文件和.h头文件。
二. lib文件
2.1 生成工具
操作系统: Win7
开发软件: VS2010
2.2 生成步骤
建立win32控制台工程MyLib(或者win32项目中下的静态库), 添加mySub.h文件以及mySub.cpp文件。
编写mySub.h文件代码
#ifndef _MYSUB_H // 这里的#ifndef可以避免头文件重复包含
#define _MYSUB_H
void mySub(int a,int b); // 这一行代码不能够写在上一行,只能另起一行写
#endif
编写mySub.cpp文件代码
#include "mySub.h" //包含头文件
#include <iostream> void mySub(int a,int b) //自定义的函数
{
std::cout<<(a-b)<<std::endl;
}
由于在工程中,没有main()函数,所以编译可能会出错。这时,点击工程,并选择工程属性,出现下图,选择静态链接库即可。
012302.png
- 这时候再按快捷键 F7,build solution即可产生lib文件。在Debug中只生成.lib文件。
2.3 lib文件的使用
新建一个.cpp文件myLibTest.cpp(用于测试)
#include <iostream>
#include "mySub.h" // 引用头文件
using namespace std; #pragma comment(lib,"MyLib.lib") // 导入上一步生成的lib文件 int main()
{
mySub(5,4); // 调用lib中的自定义函数mySub() return 0;
}
点击工程,并选择工程属性,出现下图,将附加库目录新增包含刚才生成.lib的目录。
012303.png
- 将工程项目属性中的配置类型改回至原来默认的应用程序(.exe),并执行myLibTest.cpp。
三. dll文件
3.1 生成.dll文件
新建win32项目,项目名称为SubDLL,解决方案名称为DLLTest,下一步。
选择应用程序类型为DLL,将附加选项的“导出符号”勾选上,完成。
修改SubDLL.h中的内容(将原来代码中,除预处理部分的代码外全部删除),并在后面新增你要实现的函数声明(见代码第21行)。注意:项目名为SubDLL,但此时生成的名字为 SUBDLL。
#ifdef SUBDLL_EXPORTS
#define SUBDLL_API __declspec(dllexport)
#else
#define SUBDLL_API __declspec(dllimport)
#endif /*
// 此类是从 SubDLL.dll 导出的
class SUBDLL_API CSubDLL {
public:
CSubDLL(void);
// TODO: 在此添加您的方法。
}; extern SUBDLL_API int nSubDLL; SUBDLL_API int fnSubDLL(void);
*/ //这边是新增的内容
SUBDLL_API void mySub();修改SubDLL.cpp中的内容(将原来代码中,除头文件引入部分的代码外全部删除),并在后面新增你要实现的函数声明(见代码第26行)。
// SubDLL.cpp : 定义 DLL 应用程序的导出函数。
// #include "stdafx.h"
#include "SubDLL.h" #include<stdio.h>
/*
// 这是导出变量的一个示例
SUBDLL_API int nSubDLL=0; // 这是导出函数的一个示例。
SUBDLL_API int fnSubDLL(void)
{
return 42;
} // 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 SubDLL.h
CSubDLL::CSubDLL()
{
return;
}
*/
//这边为SUM()的内容,很简易
SUBDLL_API void mySub(int a,int b)
{
printf("the result is %d",a-b);
}点击“项目”,选择“属性”,进行如下图的配置(粗体字显示部分)。
012306.png
- 构建项目(build)/生成解决方案,在项目的debug目录下面会生成很多的文件,其中包括有.dll和.lib。
3.2 dll文件的使用
3.2.1 显示调用方式
在之前“解决方案”中新建项目(选中解决方案 -> 增加 -> 新建项目),这次选择“win32控制台应用程序”,生成向导中选择“空项目”即可。取名为MyTest。
在新建项目的源文件下新建一个UseDLL.cpp文件,下面是其中的代码。
#include <iostream>
#include <Windows.h> //使用函数和某些特殊变量 using namespace std;
typedef void (*FUN)(int,int); //定义一个函数指针,确定调用函数的形参 int main()
{
const char* dllname = "SUBDLL.dll"; // 加载.dll
const char* funname = "mySub"; //SUMDLL.cpp中函数名称 HMODULE hDLL = LoadLibrary(dllname); //不要问,跟着做 if (hDLL != NULL)
{
FUN fp = FUN(GetProcAddress(hDLL,funname)); //继续做,不要问
if(fp != NULL)
{
fp(5,4);
}
else
{
cout << "Can not Find: " << funname << endl;
}
FreeLibrary(hDLL);
}
else
cout << "Can not find: " << dllname; return 0;
}点击解决方案名,选择设置启动项目 -> 通用属性 -> 启动项目 -> 单启动项目(选中UseDLL)。
运行项目,出现了错误:
Can not find:mySub
。造成这种错误的原因正是导出函数的修饰名称。在dll二进制文件中,经过编译器的“加工”,实际上有了不同的名称。这也是函数重载机制得以实现的一个技术支持。怎么办呢?我们可以通过vs2010附带工具dumpbin,找到加工以后的名称。详见dumpbin工具的使用- 在C:\Program Files(x86)\Microsoft Visual Studio 10.0\VC\bin目录下,按住shift键,鼠标右键在空白处单击,选择在此处打开命令窗口
- 输入命令: dumpbin /export 文件全名
- 将“加工”后的真是函数名复制后,粘贴。赋值给UseDLL.cpp文件中的变量funname。
- 经过上一步后,重新执行UseDLL.cpp,成功运行。详见VS2010 C++ 调用 DLL (C++编写)
为了能够使原来的UseDLL.cpp(上面第2步所示代码)成功运行,可以进行下列操作:
在生成DLL文件的SubDLL项目的源文件中新建模块定义文件createDLL.def,其中的代码如下:
LIBRARY createDLL
EXPORTS
mySub = ?mySub@@YAXHH@Z //?mySub@@YAXHH@Z 即为dumpbin工具找到的真实名。
修改SubDLL.h中的代码(去掉这些不太规范的修饰名称),修改之后重新编译生成CreateDLL.dll。
#ifdef SUBDLL_EXPORTS
#define SUBDLL_API //去掉了原来的 __declspec(dllexport)
#else //或改为 #define SUBDLL_API extern "C" __declspec(dllexport)
#define SUBDLL_API //同上
#endif
重新运行UseDLL.cpp程序,成功执行。
3.2.2 隐式调用方式
在之前“解决方案”中新建项目(选中解决方案 -> 增加 -> 新建项目),这次选择“win32控制台应用程序”,生成向导中选择“空项目”即可。取名为MyTest。
在新建项目的源文件下新建一个UseDLL.cpp文件,下面是其中的代码。
#include <iostream> extern void mySub(int,int); int main()
{
mySub(5,4);
return 0;
}
右键工程–>Linker–>General–>Additional Library Directories(附加库目录) –>找到那个SubDLL.lib所在的目录
右键UseDLL工程–>Linker->input写下lib的名称。如SubDLL.lib和你DEBUG文件下的对应(这步没有也可以,因为会在上一步的路径下寻找)。
点击解决方案名,选择设置启动项目 -> 通用属性 -> 启动项目 -> 单启动项目(选中UseDLL)
运行UseDLL.cpp程序,成功执行。
四. 小结
4.1 程序中的问题
error C2664: “LoadLibraryW”: 不能将参数 1 从“const char [10]”转换为“LPCWSTR”与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
解决方法:选中项目,然后点击属性——>配置属性——>常规——>项目默认值——>字符集,选为“使用多字节字符集"
012304.png
fatal error LNK1104: 无法打开文件:×××.lib的解决办法
一般情况是因为没有导入相应的.lib文件,或者是导入的路径有误。给项目添加库文件路径。在VS中右击项目点属性:
配置属性-->链接器-->常规-->附加目录 。在里面填上库文件所在的路径即可。
fatal error LNK1104: 无法打开文件“x x x.def”
如果不想使用xxx.def文件,可以在项目-属性-配置属性-链接器-输入 选项中,将右侧的模块定义文件删掉,这样就不会提示了。
4.2 vs的常用操作
添加头文件:
配置属性-->C/C++-->常规-->附加包含目录 加上头文件存放的目录。
添加lib文件:
- 配置属性-->链接器-->输入-->附加依赖项加入库名(×××.lib);或者是在cpp源文件中用#pragma comment(lib,"×××.lib")来代替。
- 将xxx.lib拷入工程所在目录,或者执行文件生成的目录,或者系统Lib目录中(如果lib文件是自己生成的,可以跳过这一步)。
- 给项目添加库文件路径:
在VS中右击项目点属性。配置属性-->链接器-->常规-->附加目录 。在里面填上库文件所在的路径即可。
4.3 windows小常识
在当前目录下运行命令:shift键 + 鼠标右键
首先将命令窗体属性中的快速编辑模式选中打勾,这样就可以一复制粘贴了。复制dos窗体中的内容:右键->标记->选择复制内容->回车键或者鼠标右击,粘贴的时候:鼠标右键粘贴。
dos中不能使用快捷键。
。
lib文件和dll文件的更多相关文章
- LIB文件和DLL文件的作用
(1)lib是编译时需要的,dll是运行时需要的.如果要完成源代码的编译,有lib就够了.如果也使动态连接的程序运行起来,有dll就够了.在开发和调试阶段,当然最好都有.(2)一般的动态库程序有lib ...
- 关于vs的lib文件和dll文件
一.LIB文件概念 一个lib文件是obj文件的集合.当然,其中还夹杂着其他一些辅助信息,目的是为了让编译器能够准确找到对应的obj文件 二.与DLL的区别 (1)lib是编译时需要的,dll是运行时 ...
- C/C++ 关于生成静态库(lib)/动态库(dll)文件如何使用(基于windows基础篇)
1. 首先,如何制作一个静态库(lib)? 额, 对于静态库,我们知道,里头是不应该有Main函数,它只是一个配合文件.之所以称之为lib静态库,其实就是指,我们需要用到lib里头的函数时,我们才会去 ...
- 使用Def文件导出Dll文件
模块定义 (.def) 文件是包含一个或多个描述 DLL 各种属性的 Module 语句的文本文件.如果不使用 __declspec(dllexport) 关键字导出 DLL 的函数,则 DLL 需要 ...
- 如何利用.snk文件生成DLL文件中的Publickeytoken
1.在该路径下C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin查找是否有sn.exe. 没有的话,从网上下载,注意需要的版本. 2.打开c ...
- winmd文件和dll文件的区别
今天在研究一个二维码项目,用到一个第三方组件 ZXing,因为做的是Windows应用商店程序,应用商店程序是可以引用winmd文件也可以引用dll文件,但是这两种文件ZXing都提供了,最后和同事讨 ...
- VC2010 利用 def 文件生成 dll 文件的方法
近期有个需求,要生成一个dll 文件.文件里的函数都是採用 stdcall 函数调用约定,可是不希望函数名被修饰(add 被修饰成 add@8). 这时就要用def 文件了. 比方我有以下两个函数: ...
- 编辑IL文件 修改DLL文件
本文章只是技术探讨,学习,技术上的研究而已.请支持正版. 如:KS.Gantt.DLL 为例 使用ILSpy反编译 工具 利用ildasm反编译 KS.Gantt.dll 生成IL中间代码 一般会生 ...
- 类库从自带的配置文件中获取信息(DLL文件 获取 DLL文件自带的配置信息) z
http://blog.csdn.net/shuaishifu/article/details/19602059 类库调用自身所带的配置文件中的配置信息,而不是读取应用程序所带的配置信息.代码如下: ...
随机推荐
- Web.config和App.config配置连接字符串
读取配置文件,获取连接字符串 <!-- 第一种 --> <connectionStrings> <add name="connString" conn ...
- hbase60010端口无法访问web页面
原因:HBASE1.0之后的版本web端访问的接口变更为16010
- 如何利用wx.login方法获取openid和sessionKey
1, wx.login(Object object) 调用接口获取登录凭证(code).通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key) ...
- 【MySQL】存储引擎
" 目录 #. MySQL支持的存储引擎 1. InnoDB 2. MyISAM 3. NDB 4. Memory 5. Infobright 6. NTSE 7. BLACKHOLE My ...
- C语言:计算并输出S=1+(1+2^0.5)+(1+2^0.5+3^0.5)...+(1+2^0.5+3^0.5+...+n^0.5)
//计算并输出S=1+(1+2^0.5)+(1+2^0.5+3^0.5)...+(1+2^0.5+3^0.5+...+n^0.5) #include<math.h> #include< ...
- 计算机基础 - 动态规划、分治法、memo
动态规划 ≈ 分治法 + memo def memo(func): cache = {} def wrap(*args): if args not in cache: cache[args] = fu ...
- 例题3_4 猜数字游戏的提示(UVa340)
实现一个经典“猜数字”游戏.给定答案序列和用户猜的序列,统计有多少数字位置正确(A),有多少数字在两个序列都出现过但位置不对(B). 输入包含多组数据.每组输入第一行为序列长度n,第二行是答案序列,接 ...
- beyond compare 用法
1.过滤器用法:点击小眼睛(回话-->回话设置)打开过滤器界面----设置多个过滤文件或目录直接使用回车键 2.比较时最好先设置编码以防出现乱码问题 工具-->文件格式. 3.比较时出现乱 ...
- idea 创建maven子父工程
1.创建maven工程: 2. 创建工程名称: 3.删除父工程下的src文件夹,指定打包方式为pom,添加maven依赖: 4.右键项目添加子工程: 5.添加子工程名称: 6.子工程创建成功: 7.依 ...
- redhat7.6 AIDE 系统文件完整性检查工具
1.安装AIDE yum install aide 安装完的配置文件,在/etc/aide.conf 自定义/etc/aide.conf 下面我写了对 /data/data1 目录做CONTE ...