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

生成动态库文件

姿势一:

第一步:新建一个项目

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

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

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

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

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

_declspec(dllexport) int sum(int a, int b)
{
return a + b;
}

第七步:新建一个头文件

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

第九步:编译

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

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

姿势二

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

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

第七步:添加一个头文件

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

第九步:编译

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

生成lib文件

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

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

第十三步:编译

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

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

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

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

还有一点需要注意的是,如果在源文件(.c文件)中函数的定义没有_declspec(dllexport),但是在头文件中函数的声明使用了_declspec(dllexport)此时编译产生的文件只有dll文件如果改成源文件中有_declspec(dllexport),头文件中没有_declspec(dllexport),那么编译产生的文件既有dll文件也有lib文件

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

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

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

生成静态库文件

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

第一步:

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

第三步:

第四步:

第五步:

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

int sum(int a, int b)
{
return a + b;
}

第六步:

第七步:

第八步:

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

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

但是不建议加)

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

关于lib和dll文件的区别可以看一下这一盘文章:lib 和 dll 的区别、生成以及使用详解

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

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

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

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

预处理命令使用详解----#if、#endif、#undef、#ifdef、#else、#elif

第一部分:

#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文件

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

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

上面的代码写成

#ifdef
```
#else
```
#endif

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

第二部分:

#ifdef _cplusplus
extern "C"
{
#endif
DLL int sum(int a, int b);
#ifdef _cplusplus
}
#endif

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

extern "C"
{
DLL int sum(int a, int b);
}

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

DLL int sum(int a, int b);

关于extern "C"作用,可以看一下这篇文章:深入理解C/C++混合编程(关于#ifdef __cplusplus extern "C" {...}的用法)

总结一下:

生成动态库文件

头文件:

 #pragma once
#ifdef DLL_EXPORTS
#define DLL _declspec(dllexport) #else
#define DLL _declspec(dllimport) #endif #ifdef _cplusplus
extern "C"
{
#endif
DLL int sum(int a, int b);
#ifdef _cplusplus
}
#endif

源文件:

 _declspec(dllexport) int sum(int a, int b)
{
return a + b;
}

编译之后产生:

生成静态库文件:

头文件:

 #pragma once

 #ifdef _cplusplus
extern "C"
{
#endif
int sum(int a, int b);
#ifdef _cplusplus
}
#endif

源文件:

 int sum(int a, int b)
{
return a + b;
}

编译后产生:

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

VS2017生成一个简单的DLL文件 和 LIB文件——C语言的更多相关文章

  1. 用java从0生成一个简单的excel

    用java从0生成一个简单的excel 目标 用代码实现对一个excel的基础操作,包括创建,插入文字,(好像就这些了),生成的excel可以用wps打开,如果直接用c++的文件流会生成假的xls表格 ...

  2. C++编写一个简单的DLL

    什么是DLL: 自从微软推出16位的Windows操作系统起,此后每种版本的Windows操作系统都非常依赖于动态链接库(DLL)中的函数和数据,实际上 Windows操作系统中几乎所有的内容都由DL ...

  3. Yii学习笔记之二(使用gii生成一个简单的样例)

    1. 数据库准备 (1) 首先我们建一数据库 yii2test 并建立一张表例如以下: DROP TABLE IF EXISTS `posts`; CREATE TABLE `posts` ( `po ...

  4. 如何生成动态库 .dll 的符号 .lib 文件?

    在知道拥有动态库和头文件的情况下,但没有动态库符号文件的情况下,如何静态链接动态库? 1.使用 Microsoft Visual Studio Tools 命令行命令生成 xxx.def 文件,进而使 ...

  5. [转]静态库、动态库,dll文件、lib文件,隐式链接、显式链接

    转自:https://blog.csdn.net/dcrmg/article/details/53427181 静态链接.动态链接 静态库和动态库分别应用在静态链接方式和动态链接方式中,所谓静态链接方 ...

  6. 静态库、动态库,dll文件、lib文件,隐式链接、显式链接浅见

    静态链接.动态链接 静态库和动态库分别应用在静态链接方式和动态链接方式中,所谓静态链接方式是指在程序执行之前完成所有的链接工作,把静态库一起打包合入,生成一个可执行的目标文件(EXE文件).所谓动态链 ...

  7. Windows系统查看xxx.dll、xxx.lib文件的导出函数、依赖文件等信息的方法

    1.查看xxx.dll或xxx.exe文件的导出函数.依赖文件等信息,使用Depends软件即可. 2.查看xxx.lib文件的导出函数.依赖文件等信息,使用Visual Studio附带工具dump ...

  8. 一个简单的DLL生成和测试

    DLL文件内容: SKLDll.h #ifndef _SKLDLL_H_#define _SKLDLL_H_ #ifndef DLL_API #define DLL_API extern " ...

  9. ReadDirectoryChangesW 监控文件夹 (一个简单的监控示例程序)(文件被修改了,也可以探测到)

    // .h文件 #pragma once typedef void (*PFN_NotifyAction)(DWORD dwAction, LPWSTR szFile, DWORD dwLength) ...

随机推荐

  1. Linux设备驱动程序 之 延迟执行

    长延迟 有些驱动程序需要延迟比较长的时间,即长于一个时钟滴答: 忙等待 如果想把执行延迟若干个时钟滴答,或者对延迟的精度要求不高,最简单的实现方法就是一个监视jiffies计数器的循环:这种忙等待的实 ...

  2. docker常用指令

    1.查看docker信息 docker system df 2.删除镜像 docker rmi --删除镜像 docker image prune --删除虚悬镜像 3.守护态运行 docker ru ...

  3. Qt configure 参数

    在编译QT前,可加各种参数来定制自己想要的QT库.这对需要裁减QT库的朋友来说非常重要.对于如何编译QT,可以参考:http://hi.baidu.com/agassi%5Fp/blog/item/4 ...

  4. 使用express-session实现登录效果

    本文为后端练兵内容,重复造轮子,重复造轮子才能有经验,才能生出花来. 本次练兵,采用的是数据库保存账户密码,后端通过查数据库的方式,实现账号和密码的校验. 如果验证成功,将登陆状态保存在session ...

  5. linux shell中如何让$就表示为$呢?

    答: 在$前加转义符\ 如: \$

  6. Swift 循环

    循环类型 Swift 语言提供了以下几种循环类型.点击链接查看每个类型的详细描述: 循环类型 描述 for-in 遍历一个集合里面的所有元素,例如由数字表示的区间.数组中的元素.字符串中的字符. fo ...

  7. centos7 搭建FTP

    通过yum安装vsftpd yum install -y vsftpd 修改vsftpd的配置文件 vim /etc/vsftpd/vsftpd.conf 修改配置文件如下: 1.不允许匿名访问 an ...

  8. nginx使用场景

    1. 对外开放本地封闭Server 本地server无法对外开放,nginx做反向代理,对外开发,使得外部可以访问封闭服务. upstream npm { server ; keepalive ; } ...

  9. 深入理解Flink ---- End-to-End Exactly-Once语义

    上一篇文章所述的Exactly-Once语义是针对Flink系统内部而言的. 那么Flink和外部系统(如Kafka)之间的消息传递如何做到exactly once呢? 问题所在: 如上图,当sink ...

  10. firewalld介绍

    (1).什么是firewalld? firewalld是提供了支持网络/防火墙区域(zone)定义网络链接以及接口安全等级的动态防火墙管理工具. (2).firewalld与iptables之间的关系 ...