《C语言杂记》静态库和动态库(Windows版)

2024-08-30 12:32

本文主要是介绍《C语言杂记》静态库和动态库(Windows版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

4 Windows创建和使用静态库

笔者这里使用的是VS2015,当然也可以使用其他工具。

4.1生成静态库

1.首先打开VS,先新建一个项目,选择win32控制台应用程序,当然选择win32项目也可以。
在这里插入图片描述

2.接下来选择“下一步”进入应用程序设置,这里选择静态库并去掉预编译头,当然也可以在创建项目后去掉也是可以的。最后点击“完成”即可创建项目。

在这里插入图片描述

3.创建头文件(.h)以及源文件(.cpp)
StaticLib.h

#ifndef _STATIC_LIB_H_
#define _STATIC_LIB_H_#include <iostream>namespace StaticLib
{void print_hello();  //Test function
}#endif

StaticLib.cpp

#include "StaticLib.h"void StaticLib::print_hello()
{std::cout << "Hello world!" << std::endl;
}

4.生成解决方案,我这里选择的是release

在这里插入图片描述

5.编译成功后就可以在工程目录下看到静态库。

在这里插入图片描述

4.2使用静态库

1.还是创建个普通的win32控制台程序。

在这里插入图片描述

在应用程序设置界面选择“控制台应用程序”,还是不勾选“预编译头”。

在这里插入图片描述

2.我们把上面创建lib时的头文件包含到新创建的控制台程序中,同时将lib文件复制到工程目录下。当然也可在编写测试程序时使用库所在的路径。

3.然后在测试源文件中输入以下代码:

#include "StaticLib.h"#pragma comment(lib,"WindowStaticLib.lib")int main()
{StaticLib::print_hello();system("pause");return 0;
}

#pragma comment(lib,“xxx.lib”)表示链接xxx.lib这个库。

4.最后生成并执行工程。

在这里插入图片描述

值得注意的是,生成应用程序的环境应与创建库的环境一样。

当然还有一种调用方式。

首先在测试工程目录下新建如下文件夹,将库和头文件分别拷贝到相应的文件夹中。

在这里插入图片描述

然后在配置下工程属性:

在这里插入图片描述

另外还需要属性页面中选择链接器->输入->附加依赖项中添加新生成的库。

在这里插入图片描述

同样也能得到正确结果。

另外,调用的代码更改如下:

#include "StaticLib.h"int main()
{StaticLib::print_hello();system("pause");return 0;
}

当然啦,也可以不配置链接器中的库。还是保留一下语句:

#pragma comment(lib,"WindowStaticLib.lib")

以上两种方式本质都是一样的,只是通过不同的方式来配置罢了。




5 Windows创建和使用动态库

5.1生成动态库

1.首先创建一个动态库工程。

在这里插入图片描述

和静态库一样,取消去掉预编译头,这里选择DLL。

在这里插入图片描述

2.创建头文件(.h)以及源文件(.cpp)

DynamicLib.h

#ifndef _DYNAMIC_LIB_H_
#define _DYNAMIC_LIB_H_#include <iostream>#define DLL_EXPORTS#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
extern "C" {namespace DynamicLib{DLL_API void print_hello();}
}#endif // _DYNAMIC_LIB_H_

DynamicLib.cpp

#include "DynamicLib.h"DLL_API  void DynamicLib::print_hello()
{std::cout << "Hello world!" << std::endl;
}

【注1】__declspec(dllexport)是导出符号,也就是定义需要导出函数的dll中给导出函数的函数声明前面加上导出符号,表示该方法可以导出给其他DLL或者exe使用。

【注2】C++的代码加extern “C”,是为了保证编译时生成的函数名不变,这样动态调用dll时才能。

3.选择release生成解决方案,最后生成的库如下图所示:

在这里插入图片描述

好了,动态库就创建好了。

5.2使用动态库

1.还是创建个普通的win32控制台程序。

在这里插入图片描述

2.将前面创建的动态库的头文件(.h),dll文件复制到与测试项目中。

在这里插入图片描述

3.编写测试

有两种方法调用动态库,一种隐式链接,一种显示链接

先说第一种隐式调用。隐式调用需要.h文件,.dll文件,.lib文件

在源文件加入如下代码:

#include "DynamicLib.h"#pragma comment(lib,"WindowDynamicLib.lib")int main()
{DynamicLib::print_hello();system("pause");return 0;
}

然后编译运行。

在这里插入图片描述

接下来在看看显式调用。显式调用需要.dll文件,.lib文件

#include <iostream>
#include <windows.h>typedef int(*dllfun)(void);//定义指向dll中函数的函数指针int main()
{HINSTANCE hlib = LoadLibrary(L"WindowDynamicLib.dll");if (!hlib){std::cout << "load dll error\n";return -1;}dllfun fun = (dllfun)GetProcAddress(hlib, "print_hello");if (!fun){std::cout << "load fun error\n";return -1;}fun(); //print_hello()FreeLibrary(hlib);system("pause");return 0;
}

结果和隐式调用一致。




6静态库和动态库总结

静态库:编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

静态库的代码在编译时链接到应用程序中,因此编译时库文件必须存在并且需要通过“-L”参数传递给编译器,应用程序在开始执行时,库函数代码将随程序一 起调入进程内存段直到进程结束,其执行过程不需要原静态库存在。

动态库:动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。相当于静态库,不同的应用程序可以使用同一份动态库,因此可以节省内存。另外,而且动态库还可被其他语言调用,诸如Python。

总之,静态库和动态库的载入时刻不同,静态库是编译时用到的,动态库是运行时用到的。以Windows为例,如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。




欢迎访问我的网站

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书


欢迎订阅我的微信公众号

在这里插入图片描述

这篇关于《C语言杂记》静态库和动态库(Windows版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120829

相关文章

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路

Go语言使用net/http构建一个RESTful API的示例代码

《Go语言使用net/http构建一个RESTfulAPI的示例代码》Go的标准库net/http提供了构建Web服务所需的强大功能,虽然众多第三方框架(如Gin、Echo)已经封装了很多功能,但... 目录引言一、什么是 RESTful API?二、实战目标:用户信息管理 API三、代码实现1. 用户数据

通过配置nginx访问服务器静态资源的过程

《通过配置nginx访问服务器静态资源的过程》文章介绍了图片存储路径设置、Nginx服务器配置及通过http://192.168.206.170:8007/a.png访问图片的方法,涵盖图片管理与服务... 目录1.图片存储路径2.nginx配置3.访问图片方式总结1.图片存储路径2.nginx配置

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

Go语言使用sync.Mutex实现资源加锁

《Go语言使用sync.Mutex实现资源加锁》数据共享是一把双刃剑,Go语言为我们提供了sync.Mutex,一种最基础也是最常用的加锁方式,用于保证在任意时刻只有一个goroutine能访问共享... 目录一、什么是 Mutex二、为什么需要加锁三、实战案例:并发安全的计数器1. 未加锁示例(存在竞态)

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

Go语言使用select监听多个channel的示例详解

《Go语言使用select监听多个channel的示例详解》本文将聚焦Go并发中的一个强力工具,select,这篇文章将通过实际案例学习如何优雅地监听多个Channel,实现多任务处理、超时控制和非阻... 目录一、前言:为什么要使用select二、实战目标三、案例代码:监听两个任务结果和超时四、运行示例五