在开发过程中,我们通常会有很多函数,需要多次使用或在不同的程序中使用该函数,也有可能我们会将我们写好的函数给别人使用,但是我们又不想给他源代码,毕竟代码是我们花了很多功夫写出来的,那么我们如何不发给其他人源代码而让别人使用咱们写好的函数呢?在这里我们就要用到静态链接库和动态链接库的知识了。

文章目录

  • 一.什么是库
  • 二.静态链接库的使用方法
    • 1.创建***.lib文件
    • 2.静态链接库的实现
  • 三.动态链接库的使用方法
    • 1.dll文件创建
    • .dll文件调用
      • 1.隐式调用:
      • 2.显式调用:
  • 三.导出函数名问题

一.什么是库

库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能在开发时每个源代码都从零开始,那样太花费时间了,因此库的存在很大程度上提高了我们的开发效率。

二.静态链接库的使用方法

1.创建***.lib文件

我们可以在visual studio中创建静态库,如图所示:

在创建了静态库之后可以将原有的***.cpp和***.h全部删除,使用我们新建的.h文件和.cpp文件:
完成之后可以添加代码,这里使用的所有代码都是滴水逆向三期视频里海东老师的代码:
.h(头文件)中添加代码,先进行函数声明:

#pragma onceint Plus(int x, int y);
int Sub(int x, int y);
int Mul(int x, int y);
int Div(int x, int y);

.cpp文件中添加代码:

#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;
}

在.cpp文件中incldue的是前面头文件的文件名。
点击平时的编译运行按钮,虽然提示无法运行(lib本来就无法单独运行),但已经成功生成.lib 文件了,去到 Debug 或 Release 目录下即可看到,lib 文件名和项目名一致,这里项目叫StaticLib1,生成的文件名则为StaticLib1.lib,和函数名 cpp名都无关。

2.静态链接库的实现

在完成了lib文件的创建后,我们可以将上面创建好的***.lib文件和***.h文件拷贝到需要使用的项目目录下,然后在源文件中添加代码:

#pragma comment(lib, "StaticLib1.lib")//这里需要改为自己创建的lib文件名
#include<stdio.h>
#include"MyLib.h"        //需将.h文件放入目录下才可include,
//int Plus(int x, int y);  //若没有上行的include,可自行声明.h中的函数,声明与.h中的一致即可,则可不将.h拷贝进目录下
#pragma comment(lib, "StaticLib1.lib") //在项目的"资源文件"中添加相应lib文件则不用这一条int main()
{printf("%d\n", Plus(2, 1));return 0;
}

接下来我们来讨论静态链接库的优缺点:

优点:静态链接库可以实现代码的共享,让别人可以使用或自己可以在不同程序中多次使用。

缺点:
1.我们可以通过visual C++6.0的反汇编窗口观察到:我们在调用函数时,函数的地址在.exe文件中,也就是说,我们之前写好的函数的二进制直接被编译进了程序中,可能我们编译好的函数中有很多函数在这个程序中用不上,但是编译器把它编译进了程序中,造成磁盘空间浪费。使用静态链接生成的可执行文件体积较大,造成浪费我们常用的printf、memcpy、strcpy等就来自这种静态库。
2.既然函数直接被编译进了程序中,那么当我们发现了函数的不足之处时,如果我们需要更新源代码,那么程序就需要重新编译,会给我们带来很多麻烦。

三.动态链接库的使用方法

静态链接库存在很多问题,那么动态链接库就能很好地解决静态链接库的问题。
. exe在可执行程序中没有相应库的代码,当软件运行起来再把库代码拷到内存。

1.dll文件创建

我们在visual studio中创建动态链接库:

在创建完成后我习惯将多余的文件全部删除,新增自己需要的文件:
MyDll.h文件:

#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;
}

跟创建.lib文件后一样点击平时的编译运行按钮,提示无法运行(本来就无法单独运行),但已成功生成.dll 文件,去到 Debug 或 Release 目录下即可看到,注意同样还有个.lib文件,我们后面会用到。

.dll文件调用

1.隐式调用:

首先,我们将前面创建好的.lib文件和.dll文件放入项目目录下面(静态链接库函数是放在.lib文件中的,但是动态链接库的.lib文件中,可以理解为只放了函数在哪里,而真正的函数是放在.dll文件中的。
完成之后,添加代码:

#pragma comment(lib,"dll名.lib");

然后加入函数声明:

extern "C" _declspec(dllexport) int Plus(int x, int y);

这里解释一下该代码:
extren “C”表示这是个全局函数,可以供各个其他函数调用。
“C”表示按照C语言的方式进行编译和链接,那么我们为什么要用C语言的方式进行编译呢?原因是C++函数重载,编译器为了避免出现函数名一样的函数,会将我们写好的函数名进行更改,而使用C语言方式进行编译后就不会更改我们的函数名了。
_declspec(dllexport)是告诉编译器,此函数为导出函数。

2.显式调用:

1.定义函数指针:

typedef int (_stdcall *Plus)(int,int);

2.声明函数指针变量:

lpPlus myPlus;

3.动态加载dll到内存中

HINSTANCE HModule=LoadLibrary("DllName.dll");

4.获取函数地址:

myPlus=(lpPlus)GetProAddress(hModule,"_Plus@8");

5.调用函数:

int a=myPlus(1,2);

特别说明:
1.Handle代表系统的内核对象,如文件句柄,线程句柄,进程句柄
2.HMODULE是代表程序载入的模块
3.HINSTANCE在Win32下与HMODULE是相同的东西,Win16一六
4.HWND是窗口句柄
实际上,这些都是无符号的整形,Windows之所以这样设计,主要有两个目的:
1.方便区分
2.避免使用者误进行运算
动态调用主要通过 LoadLibrary 获取 加载dll 并获取其地址,后通过 GetProcAddress 通过 dll 句柄和函数名或者函数序号(后面会说)获取真正的函数地址,得到地址,套上和该函数格式一模一样的函数指针。即可成功调用。

三.导出函数名问题

我们可以通过visual C++提供的工具DEPENDS.EXE来观看.dll文件,可以编译器为我们导出的函数名,在我们进行开发过程中,通常函数名都是见名知其意,那么别人就能够通过函数名来猜测我们函数的功能,那么我们如何隐藏函数名呢?
可以通过添加 def 文件,在源文件->添加->新建项->搜索def,即可添加def文件。
或者在文件中直接弄个空文件改成.def,然后在添加到项目的源文件中 也可以。
添加到项目的源文件后,需要在如下项目属性的这里,填入添加的def的文件名才能正常使用。
.def文件中写入一下文本:

EXPORTS  Plus    @12
Sub     @15 NONAME
Mul     @13
Div     @16

这里的Plus,Sub,Mul,DIV都是我写好的函数,如果要隐藏哪个函数名,可以根据这个来隐藏,其中@后的就是导出序号,其中NONAME表示只有序号,没有函数名,在观看.dll文件时,只能看到导出序号,看不到函数名。
由于之前我们有学习过C++,更没有学习过关于库的知识,所以在课程中可能有很多理解不到位的地方,还希望大家指出,我会非常虚心地学习,希望我们大家共同进步!

静态链接库,动态链接库【滴水逆向三期48笔记】相关推荐

  1. VC的静态链接库 动态链接库

    1.什么是静态连接库,什么是动态链接库         静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了. ...

  2. IAT表入门简析【滴水逆向三期52笔记】

    在讲IAT表之前,我们来回忆一下之前学习的知识: 如果我们将函数写在程序的源文件中,那么该函数就会被编译器直接编译到程序的二进制文件中,在程序调用该函数的时候,E8后跟的地址是直接写死的,程序直接在e ...

  3. 导入表解析,IAT表解析【滴水逆向三期53笔记】

    我们再上一章节简要介绍了IAT表,我们知道如果程序调用dll中的函数时,必须通过IAT表来找到函数,我们基本了解了IAT表之后,我们今天来讲解一下导入表,通过本章节的学习,我们可以了解导入表,也能对I ...

  4. lib库反编译C语言,C语言静态链接库(lib)与动态链接库(dll)

    今天看到了之前的笔记,看到之前写的笔记,感觉自己都不认得了~~一.静态链接库(lib) 首先创建    "在VC6中创建项目:Win32 Static Library" 在项目中创 ...

  5. C++动态链接库dll及静态链接库lib制作及使用教程

    现需将C++函数封装成动态链接库dll,网上看了好多博客教程,说的都不够全面,现提供一个很有用的视频,亲测有效,启发很大,附上链接: 视频网址 下面自己根据视频记录下制作动态链接库dll过程,防止忘记 ...

  6. 静态链接库与动态链接库 (二)动态链接库的编译与使用

    上一篇文章里大概描述linux下静态链接库的编译与使用,下面讲动态链接库的编译与使用方法. 1. 什么是动态链接库 所谓动态链接库,是指编译的时候不会把程序引用到的库插入到执行程序里,而是在执行时候才 ...

  7. 【转载】linux静态链接库与动态链接库的区别及动态库的创建

    这篇文章对于动态库的概念及使用介绍的很不错,故收藏了. 一.引言 通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件(object file)与牵涉到的函数 ...

  8. 制作静态链接库和动态链接库

    自己制作静态链接库 首先使用gcc -c只编译不连接,生成.o文件,然后使用ar工具进行打包成.a归档文件. 1.1 建立一个源文件和头文件 .C文件: #include <stdio.h> ...

  9. 动态链接库与静态链接库

    动态链接库与静态链接库 首先纠正所谓"静态连接就是把需要的库函数放进你的exe之中"的说法.在真实世界中,有三个概念:Use   static   libary,   static ...

最新文章

  1. 如何跨过Docker集群网络Weave遇到的“坑”?
  2. android和ios兼容面试题,[转]移动端常见面试题一:移动端兼容解决方案
  3. 用户和组相关的配置文件总结
  4. getchar(),putchar()用法
  5. 7-5 列出连通集 (6 分)
  6. tomcat xjar 加密_XJar Spring Boot JAR 安全加密运行工具
  7. WPF学习笔记(6):DataSet更新后台数据库个别列失败的问题
  8. curl 同时发送多个请求
  9. 百度离线地图瓦片下载器
  10. 编译原理 实验四 LR(1)分析法程序
  11. 爬虫python技术分享_Python技术分享:爬虫
  12. 你的爬虫是否徘徊在违法的边缘?
  13. 光头老法师手持尼康却能玩出佳能的效果
  14. Q绑/查绑源码/查询系统源码html下载
  15. 安卓学习笔记5.6—列表视图
  16. 泛微E9 OA 二次开发创建流程
  17. 基于stm32电子时钟设计
  18. 【资源汇总】资源汇总
  19. Smart Shooter 4 for Mac(相机控制软件)
  20. 华硕h110m主板怎么样_华硕H110M-K主板 细心的朋友会发现

热门文章

  1. win10c盘扩容_win10电脑用久了,C盘空间不够用?3步教你无损扩容C盘和分区
  2. 2.转发。基于itchat的微信消息同步机器人
  3. 找不到网络其他计算机名,局域网中找不到其他计算机怎么办
  4. 木筏世界迷你版App技术支持
  5. Springboot传参详解
  6. 半导体玻璃管标签工业级低频RFID读写器CK-S640-AP60E开发手册之产品特征与电气参数
  7. mysql的主从同步问题_mysql主从同步问题梳理
  8. 数据权限问题的几种处理和思考
  9. Linux 定义快捷键
  10. 实战中遇到的C++流文件重置的一个大陷阱 为什么ifstream的seekg函数无效