c语言库文件是dll还是lib,VS2017生成一个简单的DLL文件 和 LIB文件——C语言

下面我们将用两种不同的姿势来用VS2017生成dll文件(动态库文件)和lib文件(静态库文件),这里以C语言为例,用最简单的例子,来让读者了解如何生成dll文件(动态库文件)

生成动态库文件

姿势一:

47e076cbd4095d3910fea93e56157856.png

第一步:新建一个项目

212717ed76b6ecb05cd54cbd1af22ca2.png

第二步:选择Windows桌面向导(这里先不要去管上面的“动态链接库(DLL)”)

706877eed046d1b399ea88cce07c56a6.png

第三步:选择动态链接库,并空项目打勾√

7a6802ffcf9eb330c1739d6810e82327.png

第四步:添加一个.c源文件

7829bca473e3e8aaaefc1a7b62a205f9.png

第五步:(因为这里以C语言为例子,将后缀改为.c)

6cff4434e9669200f3f4bef0697bfdea.png

第六步:在c文件中输入一个简单的函数这里使用了_declspec(dllexport),但_declspec(dllexport)并不是必须的,后面一种方法将不使用_declspec(dllexport)

_declspec(dllexport) int sum(int a, intb)

{return a +b;

}

87f390b58315be0d2e31975687bd81b3.png

第七步:新建一个头文件

e59a39bcd34d073fe074a448f1b71bef.png

533d5f53bc0e91094dae8211fee11903.png

第八步:在头文件中输入函数的声明

9f5f54c489046de3950d51c0cb1f00a3.png

第九步:编译

017610cb652d0bd317f4e5bf7f15ab84.png

第十步:Debug文件夹下的两个文件DLL.dll和DLL.lib就是我们要使用的两个文件了

79e5f0ac9a3e5f94e3e2b877b7f1db8d.png

因为使用的_declspec(dllexport),虽然这里我们只编译了一次,却生成了dll和lib两个文件

姿势二:

46d051ecfa8857a8f0d71fbe7a7289cd.png

第一步到第五步和上面的步骤一模一样,这里从第六步开始讲起

第六步:在c文件中输入一个简单的函数(注意这里就没有使用_declspec(dllexport))

36f4ed6afcdb34ca144c1786d00de414.png

第七步:添加一个头文件

198a2d51a4c6c2b4b8043b5b74d9d5c7.png

8eb397338644b384350d19bec5fb5984.png

第八步:在头文件中输入函数的声明

1e2428d22ac0e2f673b04297e48202e4.png

第九步:编译

efb6e98f0cb5451a4f6e591cda8f32fe.png

第十步:这时在Debug文件里就可以看出两种方法的区别了,第二种方法没有加 _declspec(dllexport) 只有一个dll文件,如果我们也想要lib文件,需要额外几个步骤

2c6240aadcd16ee711f7ae793a74cf43.png

生成lib文件

第十一步:点击项目——》DLL属性

f8d478f81809ee29294ae41a03d09c27.png

第十二步:配置属性——》项目默认值——》配置类型,把动态库(.dll) 改为 静态库(.lib)

1d94afe8f4e87c4d59e842c1c83c692b.png

第十三步:编译

e5fb4f9315e3a5c16e3fbcb2e6ff769b.png

第十四步:这个时候Debug文件夹里面就多出了一个lib文件

088564bd9918ba221ce8cf05cb3a6960.png

从上面两个例子可以看出:

在生成dll文件(动态库文件)时,如果不使用_declspec(dllexport)那么就只有dll文件,在这种情况下就无法使用#pragma comment来隐式装载动态库(因为需要lib文件),只能使用LoadLibrary来显式装载动态库(使用Loadlibrary只需要dll文件)

如果使用了_declspec(dllexport)那么就既有dll文件,也有lib文件

还有一点需要注意的是,如果在源文件(.c文件)中函数的定义没有_declspec(dllexport)

45480de6083af93cdce25bfabb74c45c.png,但是在头文件中函数的声明使用了_declspec(dllexport)

a11c2ff9483bd420266e03ab510af8cd.png此时编译产生的文件只有dll文件

50c2f9738e95d586a85b16d7b8e788ec.png,如果改成源文件中有_declspec(dllexport),头文件中没有_declspec(dllexport),那么编译产生的文件既有dll文件也有lib文件

2a140560216849a75957cfa3842db606.png

(导出dll文件时最好还是在源文件和头文件中都加上_declspec(dllexport))

笔者记录了一下加与不加_declspec(dllexport)对导出dll文件大小的影响,以上面的代码为例

768ca874b3135d153d8e491e4adce890.png

(造成dll文件大小不同的原因,笔者暂时无法给出解释,待补充)

生成静态库文件

和生成dll文件步骤相似,这里就不再赘述了,直接上图

第一步:

235b6e398e22c0c9f80eebaf456ccdc0.png

第二步:建议把预编译标头的勾去掉,(不去掉也没事,只是本文为了简洁,让读者更清楚的生成步骤)

e3629fecf3463db28852a028eb4ed393.png

第三步:

a6306b06d1a48581b99985348b61f4b4.png

第四步:

f2592cb515701c9f5023ac191f45b8b2.png

第五步:

在源文件中输入以下代码:

int sum(int a, intb)

{return a +b;

}

94aae7181c1f6bd3452abd20a0670cc7.png

第六步:

8143a5d6850c130ddf1da06e22f5b5ae.png

第七步:

9aba335d0fac45ffac84b976ba7e833e.png

第八步:

79152c172dca87ed197b5a49d36596d6.png

第九步:编译,可以看到Debug文件夹下有一个lib文件

0558893a6d1bc9e9a100ffbdd0242163.png

(注意:不要像我一样傻fufu的,在导出lib文件的时候还加上_declspec(dllexport)(之前我的确这么干过),如果加了_declspec(dllexport),在Debug文件夹里面也只有lib文件,lib文件也能正常使用,

但是不建议加)

还有一点就是,生成dll文件(动态库文件)时产生的lib文件,和生成lib文件(静态库文件)时产生的lib文件的作用不相同,从文件大小也能看出来(一个1.58KB一个3.92B)

关于lib和dll文件的区别可以看一下这一盘文章:

笔者记录了一下加与不加_declspec(dllexport)对导出lib文件大小的影响,以上面的代码为例

709f1909b455eb732a56a1213dec851f.png

(至于为什么加了_declspec(dllexport)后,lib文件会出现0.02KB的差别,笔者暂时无法给出解释,待补充)

有的读者可能会发现在网上很多博客写关于生成dll文件时,头文件里面的写法是这样的

bf7e5d1bea7b154fa1b4386dcba3832c.png

刚接触预处理命令的读者看着可能会有点不好理解,下面对上面的头文件中的代码逐个分析,笔者将上面的代码分为两个个部分(对预处理命令不是很熟悉的读者可以先看一下这一篇随笔:

第一部分:

#pragma once#ifdef DLL_EXPORTS#define DLL _declspec(dllexport)

#else

#define DLL _declspec(dllimport)#endif

把上面的代码翻译一下就是:如果DLL_EXPORTS这个宏名已经被定义,那么DLL就等价于_declpsec(dllexport),否者DLL就等价于_declspec(dllimport),#pragma once保证了该头文件只被包括(#include)一次,

在很多头文件中都可以看到#pragma once,比如stdio.h

读者这个时候可能就有疑问了,明明我没有#define DLL_EXPORTS,为什么是执行#define DLL _declspec(dllexport)而不是#define DLL _declspec(dllimport)呢?

首先读者需要知道的是DLL_EXPORTS是一个预定义的宏,因为我们是生成的是DLL文件

375d97998a4f72fc93a950f180bbe54a.png

可以在属性->配置属性->C/C++->预处理器中看到

b56a2dd67e18b048f5f959e3b077fa13.png

现在读者应该清楚了,在生成DLL文件时,编译器已经预定义了DLL_EXPORTS这个宏名,如果我们是生成的应用程序

a8417d7c042d4f9bd7dfcd5f5a436382.png

上面的代码写成

#ifdef

```#else```#endif

这种形式是为了方便在使用的时候lib或者dl文件时,需要引入头文件的时候方便一点,不需要对头文件做任何的修改(因为如果我们使用的配置类型是“应用程序(.exe)”,那么就没有预定义DLL_EXPORTS)

第二部分:

#ifdef _cplusplusextern "C"{#endifDLLint sum(int a, intb);

#ifdef _cplusplus

}#endif

把上面的代码翻译一下就是:如果是C++文件(.cpp后缀)那么就是

extern "C"{

DLLint sum(int a, intb);

}

如果不是C++文件,那么就是

DLL int sum(int a, int b);

总结一下:

生成动态库文件

头文件:

1 #pragma once

2 #ifdef DLL_EXPORTS3 #define DLL _declspec(dllexport)

4

5 #else

6 #define DLL _declspec(dllimport)

7

8 #endif

9

10 #ifdef _cplusplus11 extern "C"

12 {13 #endif

14 DLL int sum(int a, intb);15 #ifdef _cplusplus16 }17 #endif

源文件:

1 _declspec(dllexport) int sum(int a, intb)2 {3 return a +b;4 }

编译之后产生:

f476934f8db82a7824f168823840bbbb.png

生成静态库文件:

头文件:

1 #pragma once

2

3 #ifdef _cplusplus4 extern "C"

5 {6 #endif

7 int sum(int a, intb);8 #ifdef _cplusplus9 }10 #endif

源文件:

1 int sum(int a, intb)2 {3 return a +b;4 }

编译后产生:

15a31b4f7ebd59c048dc9c7e620b2c52.png

到这里本文就基本结束了,上面详细叙述了生成dll文件(动态库文件)和lib文件(静态库文件)的步骤,关于lib文件和dll文件的使用将在另一篇随笔中详细介绍

来源:oschina

链接:https://my.oschina.net/u/4271149/blog/3552836

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值