静态库(lib),动态库(dll)

news2024/11/28 16:04:21

我之前有一篇文章讲过静态链接库和动态链接库,大家可以点击链接去看一下:静态链接库,动态链接库【滴水逆向三期48笔记】,由于不是系统学习Windows编程,感觉那时候就是囫囵吞枣,今天又学习了一遍,再来写一篇文章,如果大家这篇文章感觉看的不是很懂的话,大家可以两篇文章结合来看。
本篇文章主要讲解静态库和动态库的特点以及创建静态链接库和动态链接库的方法。

文章目录

  • 一.静态库(.lib)
    • 1.静态库的特点
    • 2.C语言静态库的创建示例
    • 3.静态库使用示例
  • 二.动态库
    • 1.动态库特点
    • 2.与静态库比较:
    • 3.动态库的创建
    • 4. 动态链接库的使用
      • <1>. 方法一:隐式链接:
      • <3>. 显式调用
    • 5.函数名问题

一.静态库(.lib)

1.静态库的特点

  • 运行不存在
  • 静态库源码将被直接编译到调用它的应用程序中(这里个人感觉就像将函数分文件写到项目中没啥区别)
  • 目标程序的归档

2.C语言静态库的创建示例

  • 1.首先,我们创建一个静态库项目:
    创建静态库
    1. 添加库程序,我们可以看到以及生成了需要的文件:
      需要文件
  • 添加一个头文件,写入我们需要导出的函数声明:
#pragma once
int Plus(int x, int y);
int Sub(int x, int y);
int Mul(int x, int y);
int Div(int x, int y);

之后在为我们生成的源文件中添加函数的实现过程:

// MyLib.cpp : 定义静态库的函数。
//

#include "pch.h"
#include "framework.h"

// TODO: 这是一个库函数示例
void fnMyLib()
{
}
#include "MyLib.h"

int Plus(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}

之后点击生成,我们在文件中Debug目录下就可以看到生成了.lib文件:
生成文件

3.静态库使用示例

我们来新建一个控制台项目来调用一下静态库,看看效果怎样:

  • 创建项目调用静态库:
#include <iostream>
using namespace std;
int Plus(int x, int y);
int Sub(int x, int y);
int Mul(int x, int y);
int Div(int x, int y);
#pragma comment(lib,"F:\\网安\\二进制安全\\Reverse\\滴水逆向三期\\Win32\\MyLib\\x64\\Debug\\MyLib.lib")
int main()
{
    std::cout << "Hello World!\n";
    int plus = Plus(2, 3);
    int sub = Sub(3, 2);
    int mul = Mul(5, 8);
    int div = Div(2, 3);
    cout << "plus = " << plus << endl << "sub = " << sub << endl << "mul = " << mul << endl << "div = " << div << endl;
}

我们来看看实现效果:
静态库实现效果
我们可以看到函数调用成功,说明我们的静态库创建也是成功的。

二.动态库

1.动态库特点

  • 运行时独立存在
  • 源码不会被链接到程序
  • 使用时加载(使用动态库必须让动态库执行)

2.与静态库比较:

    1. 由于静态库是将源码嵌入到实用程序中,多个程序使用时,会有多份代码,所以程序体积会很大。动态库的代码只要存在一份,其他程序使用时,通过函数地址调用,所以程序体积小。
    1. 静态库发生变化之后,新的代码需要重新链接嵌入到程序中,动态库发生变化之后,只要函数定义未发生变化,则其他使用动态库的程序不需要重新连接。

3.动态库的创建

    1. 创建动态链接库项目:
      创建动态链接库项目
    1. 添加库程序:
      还是一样,我们创建一个头文件声明我们需要的函数,但是需要注意的是需要在函数之前加上_declspec(dllexport)关键字:
#pragma once
_declspec(dllexport) int Plus(int x, int y);
_declspec(dllexport) int Sub(int x, int y);
_declspec(dllexport) int Mul(int x, int y);
_declspec(dllexport) int Div(int x, int y);

之后在MyDll.cpp文件中写入函数实现过程:

#include "MyDll.h"
int Plus(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}

创建成功后我们可以使用微软提供的工具DEPENDS.EXE查看DLL文件:
查看dll文件

    1. 库程序导出:提供给使用者库中的函数等信息
      • 方法一:
        声明导出:使用_declspec(dllexport)函数导出
        注意:动态库编译链接后,也会有lib文件的生成,是作为动态库函数映射使用,与静态库不完全相同

4. 动态链接库的使用

<1>. 方法一:隐式链接:

    1. 头文件中加入函数原型:
      可以在函数原型声明前,加入_declspec(dllimport)
    1. 导入动态库的lib文件(注意是lib文件)
#pragma comment(lib,"文件路径")
    1. 完成前两步后,就可以在程序中使用函数了

隐式链接的情况,dll文件可以存放的路径:
1.与执行文件同一个目录
2.当前工作目录
3.windows目录
4.windows/System32目录
5.Windows/System
6.环境变量PATH指定目录

<3>. 显式调用

    1. 定义函数指针
    1. 加载动态库:
HMODULE LoadLibrary(
	LPCTSTR hpFileName         //动态库文件名或全路径
);返回dll实例句柄(HINSTANCE)
    1. 获取函数地址,我们需要使用哪个函数,就获取哪个函数地址,传给函数指针
FARPORC GetProcAddress(
	HMODULE hModule,            //Dll句柄
	LPCTSTR lpProcName          //函数名称
);成功返回函数地址
    1. 使用函数
    1. 卸载动态库
BOOL FreeLibrary(
	HMODULE hModule             //dll的实例句柄
);

5.函数名问题

我们在创建了动态链接库后,使用微软提供的工具查看函数,发现函数名变成了非常奇怪的函数名,这是因为我们创建的动态链接库是C++语言实现的,而C++具有的函数重载机制,编译器会考虑到函数重载问题,自己帮我们改了函数名称。
这里给出解决方法:

  • 模块定义文件.def
    增加def文件
    写入:
    LIBRARY DLLFunc //库
    EXPORT //库导出表
    DLLNUL @1 //自定义导出序号

今天的分享就到这里,如果大家还有不理解的地方,大家随时可以私信我,如果发现文章中的错误,希望大家及时指出来,我会非常虚心地学习,希望大家共同进步!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512797.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Keil生成外部Nor Flash下载算法,并使用J-Flash直接烧录(以W25Q64为例)

需要的软件&#xff1a; Keil STM32CubeMX J-Flash 参考文档&#xff1a; 方法1&#xff1a;在Keil中点击Help→uVision Help&#xff0c;然后再搜索框中输入FLM&#xff0c;点击列出主题&#xff0c;可以看到生成下载算法的大致步骤&#xff1a; 方法2&#xff1a;在ARM Ke…

带你玩转三子棋—【C语言】

目录 前言&#xff1a; 1. 菜单的打印 2. game函数的实现 2.1 初始化棋盘 2.2 显示棋盘 2.3 玩家下棋 2.4 电脑下棋 2.5 判断输赢 2.6 判断棋盘是否满了 3. 全部代码 3.1 game.h 3.2 game.c 3.3 test.c 前言&#xff1a; 为了实现三子棋&#xff0c;首先我们应该…

frp将配置写在代码中重新打包

frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。在有些情况下我们需要隐藏配置信息&#xff0c;尤其是客户端&#xff08;比如我们要在第三方电脑…

第五章 总结及作业(123)【编译原理】

第五章 作业【编译原理】 前言推荐第五章 总结5.1自下而上分析基本问题 5.1.1归约5.1.2规范归约简述5.1.3 符号栈的使用与语法树的表示 5.2 算符优先分析5.2.1算符优先文法及优先表构造算法&#xff1a;构造FIRSTVT集算法&#xff1a;构造LASTVT集算法&#xff1a;构造优先表5.…

Google I/O 2023 - 一文快速总结 Flutter Dart 的现状和未来

随着 Google I/O 2023 的发布&#xff0c; Flutter 3.10 和 Dart 3.0 也都正式发&#xff0c;不得不说如今 Dart 的版本号终于快追上 Flutter 得版本号了&#xff0c;特别随着 Dart 3 的发布&#xff0c; Flutter 在 records 和 patterns 的加持下&#xff0c;开发体验终于开始…

LlamaIndex :面向QA 系统的全新文档摘要索引

在这篇博文中&#xff0c;我们介绍了一种全新的 LlamaIndex 数据结构&#xff1a;文档摘要索引。我们描述了与传统语义搜索相比&#xff0c;它如何帮助提供更好的检索性能&#xff0c;并通过一个示例进行了介绍。 背景 大型语言模型 (LLM) 的核心场景之一是对用户自己的数据进…

MapReduce框架

TextInputFormat 1&#xff09;FileInputFormat实现类 思考&#xff1a;在运行MapReduce程序时&#xff0c;输入的文件格式包括&#xff1a;基于行的日志文件、二进制格式文件、数据库表等。那么&#xff0c;针对不同的数据类型&#xff0c;MapReduce是如何读取这些数据的呢&…

Postman 如何关联接口测试并设置全局变量(带有token鉴权)

一、登陆接口 创建一个request请求 在Tests中添加JavaScript代码&#xff0c;用来获取鉴权&#xff1a; var jsonData JSON.parse(responseBody); var Authorization jsonData.data.access_token; console.log(Authorization) pm.globals.set(‘Authorization’,Authorizatio…

solr快速上手:solr简介及安装(一)

0. 引言 虽然现在主流的搜索引擎组件已经es主导&#xff0c;但不乏有部分“老”项目依旧在采用solr&#xff0c;当遇到这类项目时&#xff0c;如何快速上手solr组件&#xff0c;以及后续如何拓展深入研究solr的途径成为问题&#xff0c;本期我们的目的就是带大家来快速上手sol…

2023 年第三届长三角高校数学建模竞赛赛题浅析

为了更好地让大家本次长三角比赛选题&#xff0c;我将对本次比赛的题目进行简要浅析。数模模型通常分为优化、预测、评价三类&#xff0c;而本次数学题目就正好对应着A、B、C分别为优化、预测、评价。整体难度不大&#xff0c;主要难点在于A题的优化以及B、C的数据收集。稍后&a…

QT5.12.6 + mysql5.5.9 出现 Driver not loaded Driver not loaded

由于我重装了电脑系统&#xff0c;qt 和mysql均进行了软件版本的升级&#xff0c; 在使用数据库模块时&#xff0c;出现了如下问题&#xff1a; Driver not loaded Driver not loaded 排除问题一&#xff1a; pro文件中是否加载了sql模块 查看pro文件&#xff0c;发现 有此模…

React的两种组件创建方式(二)

react是面向组件编程的一种模式&#xff0c;它包含两种组件类型&#xff1a;函数式组件及类式组件 函数式组件 一个基本的函数组件长这个样子 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>hell…

java报错-->java.lang.IllegalAccessError

1、前言 在gradle中运行main方法突然出现如下错误 Exception in thread "main" java.lang.IllegalAccessError: class XXX.util.ImageBorderUtils (in unnamed module 0x4bd4bcd4) cannot access class sun.font.FontDesignMetrics (in module java.desktop) becaus…

使用宝塔在Linux面板搭建网站,并实现公网远程访问「内网穿透」

文章目录 前言1. 环境安装2. 安装cpolar内网穿透3. 内网穿透4. 固定http地址5. 配置二级子域名6. 创建一个测试页面 转载自远程内网穿透的文章&#xff1a;Linux使用宝塔面板搭建网站&#xff0c;并内网穿透实现公网访问 前言 宝塔面板作为简单好用的服务器运维管理面板&#…

数据结构与算法(Java版) | 数组模拟队列的思路分析与代码实现

思路分析 上一讲我们讲过&#xff0c;队列既可以用数组来实现&#xff0c;也可以用链表来实现&#xff0c;但由于我们比较熟悉数组这种结构&#xff0c;所以这里我会先给大家讲一下数组这种实现方式&#xff0c;至于链表这种实现方式&#xff0c;那就以后有机会再说吧&#xf…

探索人工智能新纪元:Pre-Training 快速指南,轻松上手

theme: orange 预训练 Pre-Training 已被证明是当前人工智能范式中最重要的方面之一&#xff0c;大型语言模型&#xff0c;要转变为通用引擎&#xff0c;需要预训练。 什么是预训练模型 人工智能中的预训练至少部分受到人类学习方式的启发。我们不需要从零开始学习一个主题&…

肝一肝设计模式【七】-- 代理模式

系列文章目录 肝一肝设计模式【一】-- 单例模式 传送门 肝一肝设计模式【二】-- 工厂模式 传送门 肝一肝设计模式【三】-- 原型模式 传送门 肝一肝设计模式【四】-- 建造者模式 传送门 肝一肝设计模式【五】-- 适配器模式 传送门 肝一肝设计模式【六】-- 装饰器模式 传送门 文…

JavaWeb:Cookie、Session、JSP、JavaBean、MVC 三层架构

文章目录 JavaWeb - 03一、Cookie1. Cookie 应用2. 注意点 二、Session三、JSP1. 概述2. JSP 基础语法和指令&#xff08;了解&#xff09;3. 内置对象及作用域4. JSP 标签、JSTL 标签 四、JavaBean五、MVC 三层架构1. 之前的架构2. 现在的 MVC 三层架构 注意&#xff1a; Java…

Feign和OpenFeign

1.Feign和OpenFeign的关系 Feign Feign是一个声明式的Web服务客户端&#xff08;Web服务客户端就是Http客户端&#xff09;&#xff0c;让编写Web服务客户端变得非常容易&#xff0c;只需创建一个接口并在接口上添加注解即可。 Feign是Spring Cloud组件中一个轻量级RESTful的H…

MySQL基础学习---7、子查询

子查询 子查询指的是一个查询语句嵌套在另一个查询语句内部的查询&#xff08;从MySQL4.1开始引入&#xff09;。1、子查询的基本使用 语法格式&#xff1a;select select_listfrom tablewhere expr operator(select select_listfrom table); 说明&#xff1a;1、子查询&…