Windows环境下的静态库和动态库的使用详解

news2024/11/23 8:26:52

文章目录

  • 简介
  • lib库的详细说明
    • 第一种是静态lib库
    • 第二种是lib导入库
    • 两种库的说明
    • 两种lib库的相同点和不同点
  • 在visual studio下静态lib库的导出和使用
    • 导出过程演示
    • 使用过程演示
      • 使用方式一
      • 使用方式二
      • 使用方式三
      • 使用方式四
      • 使用方式五
      • 使用方式六
      • 使用方式七
      • 其他组合方式
  • 在visual studio下动态链接dll库的导出和使用
    • 导出过程演示
      • 第一种方式导出
      • 第二种方式导出:
    • 使用过程演示
      • 隐式链接
      • 显式链接

简介

在Windows系统下常见的库有两种一种是以.lib为扩展名的库,也叫lib库。lib库实际上分为两种:一种是静态链接lib库或者叫做静态lib库,另一种是动态链接库dll库的lib导入库或称为lib导入库。以dll为扩展名的库叫dll库,dll库只有一种就是用于动态链接的动态链接库(也叫dll库,dll是:dynamic link library的英文单词首字母缩写)。在发展史上,动态链接库的出现晚于静态链接库的出现。

lib库的详细说明

第一种是静态lib库

静态lib库,包含了所有的代码实现的,是源代码文件.c或.cpp文件编译生成的,这个lib库就是文本形式的源代码编译后的二进制形式代码。

第二种是lib导入库

lib导入库,这个库里只是相应的dll文件中的所有函数在dll文件中的地址的说明。也就是这个lib导入库里没有函数的具体实现,只是对相应的dll文件的说明。
也就是说目前以.lib为后缀的库有两种,一种为静态链接库(static library,简称“静态库”),另一种为动态链接库(DLL,简称“动态库”)的导入库(import library)。

两种库的说明

从两种库的说明可以看出,静态lib库文件里是包含了所有的代码的,所以只要导入后,使用链接器链接生成exe文件后,那么exe文件就可以直接使用exe 内部的代码了。这个静态链接lib库的过程就相当于把静态lib库里的所有二进制的代码复制到exe文件中。所以,链接完后,静态lib库文件就不需要了。最后, 我们只要exe就行了。这个lib在链接完后,就已经失去价值了。只有下次再编译生成exe文件时,才再此需要。发版时,只提供给别人exe就行,不需要提供静态lib库。缺点是导致exe文件太大。每次修改静态lib库文件里的代码,都需要重新编译生成新的exe文件。优点是:依赖性小。小的应用程序,适用使用静态lib库,大的应用程序不适合使用静态lib库。
lib导入库可以说明相应的dll库的内部结构,简直就对dll内部了如指掌,我们通过lib导入库,再把相应的dll文件放到合适的位置(这个再后面再说具体放到哪里),程序运行时,就可以轻松调用到dll里面的函数。

两种lib库的相同点和不同点

相同点:两种lib都是用于编译的链接阶段,都把自身的内容复制拷贝到exe文件内,在正确生成exe后,两种lib库的使命也就完成了。也就是说后续运行exe程 序,就用不到了(即程序的运行阶段)。这里要说明一下,虽然lib导入库中不存在,函数的具体实现,但是其里面有函数具体在哪个dll文件中的说明。那么在源代码生成的目标文件,在链接阶段,通过在lib导入库文件中,查到相应的外部函数的实现在对应的dll文件中的地址说明,也就保证链接阶段的正确通过,而其相应的具体的dll文件并不参与整个编译的阶段,而是在程序运行阶段才实际需要到,真正的实现了说明和实现的分离。
不同点:静态库是一个或者多个.obj目标文件的打包,静态库只是一个“壳子”,静态库报错的话,会定位到某个.obj目标文件。静态库和导入库的区别很大,他们本质是不一样的东西。静态库本身就包含了实际执行代码、符号表等;而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

在visual studio下静态lib库的导出和使用

导出过程演示

1.首先创建一个空项目或者创建一个静态库项目(两者其实没啥区别,区别在于 项目属性页–>配置属性–>常规–>配置类型的默认选项:空项目的为应用程序(.exe),而静态库项目的为:静态库(.lib)),这个如果新建的是空项目的话,可以手动切换成静态库(.lib)。
在这里插入图片描述在这里插入图片描述
2.这里选择新建一个空项目,点击进入后,配置新项目。
在这里插入图片描述
4. 创建头文件 add_sub.h文件。
在这里插入图片描述
头文件内容:
在这里插入图片描述
源文件add_sub.cpp,里面的函数是对add_sub.h中的函数原型的具体实现。【注意:我们这里没有涉及到类,所以函数都是全局的,这里,在源文件中不引入头文件也是可以的,只根据add_sub.cpp也可以生成静态库,但是最好引入头文件,如下我们这里就加上了头文件】
在这里插入图片描述
下面是编译前的属性页设置:鼠标放到项目名上(不是解决方案名称),点击鼠标右键,在弹出框中,选择属性(R),弹出下面界面:
在这里插入图片描述
静态库的设置主要看上面这个界面:输出目录:指定的编译后的静态库文件的生成存放的位置。

在这里插入图片描述
在这里插入图片描述
目标文件名:这里默认是以当前工程名做为生成的静态库的文件名。
在这里插入图片描述
其实上面的都按照默认就行了,就是配置类型确认为**静态库(.lib)**就行了。
还有一处C/C++下的预编译头菜单的设置:设置为不使用预编译头,网上有人说,设置预编译头,可以提高编译效率,具体也不是太清楚。
在这里插入图片描述

启动编译静态库: 点击 生成 下的 生成XXX或者 通过Ctrl+B生成。不要像含main函数的 项目那样,直接点击 本地Window调试器。否则会在编译完成后,尝试运行lib文件,提示报错。
在这里插入图片描述
生成后的文件:
在这里插入图片描述
至此一个简单的静态库的生成就演示完毕了。

使用过程演示

一般情况下,我们在项目中使用静态链接库时,都需要头文件和静态lib库文件的搭配。头文件中主要放置宏定义,函数原型等,保证 链接之前的代码的正常编译,以及使用函数原型充当目标文件中的函数符号。
也是在visual studio下演示
新建一个空项目:
在这里插入图片描述

在创建的当前项目下,新建两个目录 include和lib。(在其他地方新建也可以)。
新建
在这里插入图片描述
在这里插入图片描述

使用方式一

在这里插入图片描述
关键点:通过#include命令通过相对路径的方式引入头文件,通过#pragma comment()命令 通过相对路径的方式添加lib
库。也可以写绝对路径,但是绝对路径的话,不灵活。采用方式一,属性页界面不用设置。

使用方式二

在这里插入图片描述
关键点:这种方式变化的就是:#pragma comment(lib,“./lib/Static_lib_proj”)里的lib库文件的扩展名不写。这里会根据前一项的类型lib,编译器会把Static_lib_proj当成文件名,然后拼接扩展名.lib后,查找Static_lib_proj.lib文件。注意没有#pragma comment(dll,“xxxxx”);这种方式,注意没有动态库的类型,#pragma comment命令和动态库的引入没有直接关系。动态库的引入我们在动态库的使用环节再介绍。

使用方式三

在这里插入图片描述
在这里插入图片描述
关键点: 在当前工程属性页下的【配置属性】下的【C/C++】下的【常规】下的 【附加包含目录】添加 头文件所在目
录。这种方式下#include里就可以直接写头文件名。因为IDE会智能的按附加包含目录里配的路径下去搜索
头文件。这种方式设置头文件的目录时,源代码里引入头文件时,也可以用#include <add_sub.h>。即可用< >
代替" “。即能用< >的时候,也一定能双引号” “。反过来 能双引号” "的时候,不一定能用< >。关于这个#include
<add_sub.h>和#include "add_sub.h"引入方式的区别,单独写篇文章再讲;

使用方式四

在这里插入图片描述

在这里插入图片描述
关键点: 方式三和方式四的源代码是一样的,不同的是工程属性页的设置:这里是通过【配置属性】下的【VC++目录】下的【包含目
录】里添加了头文件的路径。方式四的包含目录和方式三的附加包含目录的区别,我们会单独讲解。这也是IDE的历史遗留问
题,就目前来说,设置的效果都只会影响到当前项目了。

使用方式五

在这里插入图片描述
在这里插入图片描述
关键点:这里源代码中没有写lib库的具体路径,只写的文件名,它会去到【配置属性】下的【VC++目录】下的【库目
录】下的路径里去搜索文件名为Static_lib_proj.lib的库文件。

使用方式六

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用方式七

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

关键点:属性页设置里 方式七比方式六多设置了个 【链接器】下的【输入】下的【附加依赖项】,在附加依赖项里,我们填写上要依赖
的lib库的名称。这样代码里就不用添加#pragma comment(lib,“Static_lib_proj.lib”) 这句代码了。编译链接时,会自动通过附加
库目录里的路径+附件依赖项里的文件名链接到。

其他组合方式

这里只是列举里常见的几种方式,还有其他组合方式,这里就不在讲解了,相信大家也都有所领悟了。

在visual studio下动态链接dll库的导出和使用

导出过程演示

第一种方式导出

1.创建一个动态库项目
在这里插入图片描述
在这里插入图片描述
2.创建头文件 mathDll.h

//__declspec(dllexport)修饰符指示编译器和链接器从DLL导出函数或变量,以便其他应用程序可以使用它
//这里使用的宏定义来代替 这两个修饰符__declspec(dllexport) 和 __declspec(dllimport)
#pragma once
#ifdef EXPORTDLL_EXPORTS //此宏的定义在,源文件mathDll.cpp中
#pragma message("====dllexport=====")
#define EXPORTDLL_API __declspec(dllexport)//生成DLL库时需要
#else
#pragma message("====dllimport====")
#define EXPORTDLL_API __declspec(dllimport)//在应用程序中使用DLL库时需要
#endif

#ifdef __cplusplus //C++环境时,执行extern "C" { }
extern "C" {
#endif
	EXPORTDLL_API int add(int a, int b);			//加法
	EXPORTDLL_API int sub(int a, int b);			//减法
	EXPORTDLL_API int multiply(int a, int b);		//乘法
	EXPORTDLL_API float divide(float a, float b);	//除法

#ifdef __cplusplus
}
#endif

3.创建源文件mathDll.cpp

//#include "pch.h"
//自定义一个宏,此宏在mathDll.h中被使用,所以这里要在#include "mathDll.h"前定义在有效
#define EXPORTDLL_EXPORTS
#include "mathDll.h"
EXPORTDLL_API int add(int a, int b)
{
	return a + b;
}

EXPORTDLL_API int sub(int a, int b)
{
	return a - b;
}

EXPORTDLL_API int multiply(int a, int b)
{
	return a * b;
}

EXPORTDLL_API float divide(float a, float b)
{
	if (b != 0)
		return a / b;
	else
		return (float)0;
}

4.dllmain.cpp(创建项目时自动生成的)

//此dllmain里的内容 是创建动态库dll时自动添加的,暂切不管其内容。
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h" //visual studio 2017 或更早的版本是 "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,             //模块句柄
                       DWORD  ul_reason_for_call,   //调用原因
                       LPVOID lpReserved  //参数保留,好像没什么用
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:    //DLL被某个程序加载
    case DLL_THREAD_ATTACH:     //DLL被某个线程加载
    case DLL_THREAD_DETACH:     //DLL被某个线程卸载
    case DLL_PROCESS_DETACH:    //DLL被某个程序卸载
        break;
    }
    return TRUE;
}

5.pch.h (创建项目时自动生成的)

// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。

#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"

#endif //PCH_H

6.framework.h(创建项目时自动生成的)

#pragma once

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>

6.pch.cpp(创建项目时自动生成的)

// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"

// 当使用预编译的头时,需要使用此源文件,编译才能成功。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最终生成结果:(我们需要的就是dll和lib这两个文件,其他文件暂时没有接触到,不便讲解)
在这里插入图片描述

第二种方式导出:

创建模块定义文件.def以列出导出的DLL函数。(这种方式暂时没有遇到过,后面遇到了再补上)

使用过程演示

1.新建一空项目
在这里插入图片描述
调用DLL动态库有两种方式。一种是隐式链接 ,一种是显示链接

隐式链接

需要准备的是头文件mathDll.h,导入库Dll_export_proj.lib,动态库Dll_export_proj.dll。
mathDll.h和Dll_export_proj.lib在程序编译链接时需要。Dll_export_proj.dll库是在程序运行时才需要的。
其中头文件和导入库的引入和使用静态库时的方式是一样的。
下面说下动态库的放置位置(有两种):1. C:\Windows\SysWOW64(放win32或x86平台编译的动态库) 和C:\Windows\System32(放置x64平台编译的动态库)。当我们的可执行文件是64位的系统就自动去C:\Windows\System32下搜索想要的dll文件。当我们的可执行文件是32位的就去C:\Windows\SysWOW64下搜索想要的dll文件。2.还可以放到与生成的可执行文件位于同一目录下。查找顺序先是 2,然后是1。

#include "iostream"
using namespace std;
#include "./include/mathDll.h"
#pragma comment(lib,"./lib/Dll_export_proj.lib")

int main(int argc, char* argv[])
{
	int a = 10, b = 5;
	cout << add(a, b) << endl;
	cout << sub(a, b) << endl;
	cout << multiply(a, b) << endl;
	cout << divide(a, b) << endl;
	system("pause");
	return 0;
}

这里在点击 生成解决方案后或生成(项目名)后,会生成exe文件。我们把dll库放到和exe相同的目录下(选择第二种)。
在这里插入图片描述
双击exe文件,可以正常执行main函数中调用的动态库里的函数。
在这里插入图片描述
没有把dll库放到指定的位置,时双击exe文件的效果:
在这里插入图片描述

显式链接

是由编程者用API函数加载和卸载DLL来达到调用DLL的目的,使用上较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。 显式的调用:是指在应用程序中用LoadLibrary显式的将自己所做的动态连接库调进来,动态连接库的文件名即是上面两个函数的参数,再用GetProcAddress()获取想要引入的函数。自此,你就可以象使用如同本应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用FreeLibrary释放动态连接库。直接调用Win32 的LoadLibary函数,并指定DLL的路径作为参数。LoadLibary返回HINSTANCE参数,应用程序在调用GetProcAddress函数时使用这一参数。GetProcAddress函数将符号名或标识号转换为DLL内部的地址。程序员可以决定DLL文件何时加载或不加载,显式链接在运行时决定加载哪个DLL文件。使用DLL的程序在使用之前必须加载(LoadLibrary)加载DLL从而得到一个DLL模块的句柄,然后调用GetProcAddress函数得到输出函数的指针,在退出之前必须卸载DLL(FreeLibrary)。这种方式只需要DLL文件就行,不需要头文件和lib导入库。

#include "iostream"
using namespace std;
//显示链接时 必需要pch.h
#include "pch.h"	//visual studio 2017 或更早的版本是 "stdafx.h"
int main(int argc, char* argv[])
{
	HMODULE hModule;   //模块句柄,可以把这个句柄定义为全局的,这样在其他文件中也可以使用

	//定义函数指针
	typedef int(*ADD)(int a, int b);
	typedef int(*SUB)(int a, int b);
	typedef int(*MULTIPLY)(int a, int b);
	typedef float(*DIVIDE)(float a, float b);

	//通过LoadLibrary()函数加载DLL,是运行时的动态加载,指定路径下实际有没有DLL文件,不影响程序的编译。
	hModule = ::LoadLibrary(L"Dll_export_proj.dll");//调用DLL,先找当前文件夹(即exe的同级目录),如果没有,就会去System32\SysWOW64下查找 
	//hModule = ::LoadLibrary(L"D:\\dll\\Dll_export_proj.dll");//也可以指定带目录的路径,当程序运行代码执行到这里时,会去这里找DLL。
	if (hModule == NULL) {
		MessageBox(NULL, L"DLL加载失败", L"Mark", MB_OK);//当执行exe文件时,DLL文件加载失败时的弹框
		return 0;
	}

	//获取相应DLL函数的入口地址(即函数指针)
	ADD add = (ADD)::GetProcAddress(hModule, "add");
	SUB sub = (SUB)::GetProcAddress(hModule, "sub");
	MULTIPLY multiply = (MULTIPLY)::GetProcAddress(hModule, "multiply");
	DIVIDE divide = (DIVIDE)::GetProcAddress(hModule, "divide");

	//----------------------调用函数----------------------
	//加
	if (add != NULL) {
		cout << "a+b=" << add(10, 5) << endl;
	}

	//减
	if (sub != NULL) {
		cout << "a-b=" << sub(10, 5) << endl;
	}

	//乘
	if (multiply != NULL) {
		cout << "a+b=" << multiply(10, 5) << endl;
	}

	//除
	if (divide != NULL) {
		cout << "a+b=" << divide(10, 5) << endl;
	}

	FreeLibrary(hModule);   //释放句柄,即释放已加载的动态库

	system("pause");
	return 0;
}

点击生成解决方案后,执行exe文件的效果如下:
在这里插入图片描述

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

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

相关文章

2022-04-24:用go语言重写ffmpeg的muxing.c示例。

2022-04-24&#xff1a;用go语言重写ffmpeg的muxing.c示例。 答案2022-04-24&#xff1a; 本程序的大体过程如下&#xff1a; 打开输出文件并写入头部信息。 添加音频和视频流&#xff0c;并为每个流创建 AVCodecContext 对象&#xff0c;根据输入格式设置编码器参数&#x…

Volatile与ThreadLocal

一&#xff1a;Volatile 线程安全三方面 1 可见性&#xff1a;一个线程对共享变量修改&#xff0c;另一个线程可以看到最新结果 2 有序性&#xff1a; 一个线程内&#xff0c;代码编写按顺序执行 3 原子性&#xff1a; 一个线程内多行代码以一个整体运行&#xff0c;期间不能…

查询网站ip地址

IP地址是Internet Protocol&#xff08;互联网协议&#xff09;的一部分&#xff0c;是一个32位的数字&#xff0c;用于标识网络中的设备。它可以让不同的设备在网络上进行通信和交流&#xff0c;是网络通信的基础。IP地址的应用非常广泛&#xff0c;它可以用于识别和定位设备&…

最新数据, 芯片工程师平均月薪高达2.56W !

近日&#xff0c;据2023年一季度经济运行数据统计&#xff0c;其中提及全国居民人均可支配收入达到10870&#xff0c;同比增长3.8%。 2023年第一季度中&#xff0c;共有20个行业平均月薪超1W&#xff0c;除了大家所熟悉的金融行业薪资水平排名靠前&#xff0c;一些高技术制造业…

iOS SFSpeechRecognizer 语音识别

SFSpeechRecognizer 属于 Speech 框架&#xff0c;在 iOS 10 首次出现&#xff0c;并在 iOS13 中进行了比较重大的更新&#xff0c;在 iOS 13 上支持离线语音识别以及语音分析。WWDC2019 展示了其在 AI 领域的进步&#xff0c;其中 iOS 13 设备内置语音识别就是一项比较不错功能…

第二届中国抗衰老化妆品产业发展论坛暨国粹国妆品牌与文化交流会在京召开

消费日报网讯&#xff08;记者 王儒&#xff09;4月18日&#xff0c;以“国粹国妆 抗衰美丽“为主题的第二届中国抗衰老化妆品产业发展论坛暨国粹国妆品牌与文化交流会在北京召开。大会旨在挖掘国粹力量&#xff0c;搭建沟通交流合作的平台&#xff0c;推动中国高端化妆品品牌建…

网工神器:PNETLab模拟器踩坑过程

目录 0、前言 1、PNETLab介绍 2、下载安装 2.1 下载 2.2 导入 2.3 启动 2.4 注册和登录 3、汉化 4、镜像 5、控制台 5.1、HTML控制台 5.2、默认控制台 6、总结 0、前言 由于工作需要&#xff0c;想测试一下SD-WAN&#xff0c;手边既没有测试环境又没有测试设备。突然想…

八年软件测试生涯,是时候做出改变了

五年前&#xff0c;我在南方的大城市&#xff1a;广州&#xff0c;做着一个快乐的游戏测试&#xff0c;工作不太忙&#xff0c;对一切技术充满了好奇心。测试工作不专业&#xff0c;也不受重视。但我有自己的快乐。工作不忙的时候&#xff0c;我今天学学Python&#xff0c;明天…

uniapp + vue3开发中组合式函数必须是一个同步函数

目录 vue3中的组合式函数用法&#xff1a; 官网示例异步组合式函数&#xff1a;同步函数写法 改造成导出async组合式函数时&#xff1a; uniapp无法使用async组合式函数的原因&#xff1a; vue3中的组合式函数使用时&#xff0c;导出的组合式函数必须是一个同步函数。 vue3…

塔望3W消费战略全案丨元力参堂:从0到1,超级大单品跨越式增长

元力参堂 客户&#xff1a;上海弥富生物科技有限公司 品牌&#xff1a;元力参堂 服务&#xff1a;3W消费战略 品牌全案 项目背景 2020年初&#xff0c;一场突如其来的疫情让我们按下了暂停键&#xff0c;大家经历着疫情的考验。长时间的隔离、封闭影响到生产、消费、投资、物…

ChatGPT3分钟写的千字福尔摩斯小说,老师都分辨不出真假

AI写小说&#xff01;感受ChatGPT3分钟写的千字福尔摩斯小说&#xff01;逆天&#xff01; ChatGPT写悬疑小说 其实在最初&#xff0c;测试者要求ChatGPT写一个5000字的故事&#xff0c;但AI居然直接罢工&#xff0c;还言简意赅&#xff1a;“不&#xff0c;太长了。” 于是…

MySQL库和表的操作

1 什么是数据库&#xff1f;什么是SQL&#xff1f; 科学的组织和存储数据&#xff0c;如何高效获取和维护数据 2 一条SQL语句的执行过程 SQL语句就是一个数据库能够识别的指令语言 在实际操作过程中&#xff0c;创建连接&#xff0c;连接MySQL的server mysql -uroot -P330…

PMP证书备考攻略+PMP知识点汇总

一&#xff0c;考PMP好处多 1.能力提升 大型项目&#xff0c;领导专业团队 2.升职加薪 晋升管理岗&#xff0c;优先升职加薪 3.招投标加分 具有PMP证书&#xff0c;企业招标有加分 4.转型利器 助力转型&#xff0c;拓宽职业发展 5.公司支持 企业鼓励学习&#xff0c;报销费用 6…

LVS负载均衡-DR

1.DR模式中每台主机都有一个VIP地址 虚拟网址放在lo网卡上&#xff08;回环网卡&#xff09; arp_ignore1 Arp_announce2 系统不使用IP包的源地址来设置ARP请求的源地址&#xff0c;而选择发送接口的IP地址 2.内核参数修改 3.vim /etc/rc.conf 开机自启动 Chmod x /etc/rc.d…

Spring Security实战(六)—— 跨域与CORS

跨域是一种浏览器同源安全策略&#xff0c;即浏览器单方面限制脚本的跨域访问。 一、认识跨域 跨域&#xff08;Cross-Origin&#xff09;指的是在Web开发中&#xff0c;当一个网页的内容要从不同源&#xff08;即不同的域名、协议或端口&#xff09;获取时&#xff0c;就会发…

时序分析与时序约束知识总结

文章目录 时序分析如何查看时序报告时序分析的分类和任务HOLD违例修复&#xff1a;SETUP违例修复&#xff1a;时序违例的修复 时序约束约束的分类时序约束的作用SDF文件OCVPVT共同路径悲观效应(CPP)setup time与hold time和什么有关clock Jitter与clock Skewsetup和hold裕度计算…

10.java程序员必知必会类库之邮件

前言 邮件功能在当前互联网应用中已经是很成熟的功能&#xff0c;也是作为java程序员应该掌握的技能。常见使用场景有&#xff1a; 电商软件开电子发票&#xff0c;需要发到用户邮箱里面生产实时报警&#xff0c;需要发到邮箱里面银行软件申请的征信报告&#xff0c;电子账单…

Django框架之Admin站点管理

Django的强大体现在其内置的Admin模块可以使得开发人员在不做任何编码的情况下就拥有网站后台管理功能。 概述 内容发布&#xff1a;负责添加、修改、删除内容 内容访问查看 配置admin应用 在settings.py中添加django.contrib.admin 默认已添加 创建管理员账户 python man…

九、1~8文章的阶段案例

一、案例 现在我们来做一个相对综合一点的练习&#xff1a;书籍购物车 案例说明&#xff1a; 1.在界面上以表格的形式&#xff0c;显示一些书籍的数据&#xff1b;2.在底部显示书籍的总价格&#xff1b;3.点击或者-可以增加或减少书籍数量&#xff08;如果为1&#xff0c;那…

【论文精读】ISBI 2022 - Retinal Vessel Segmentation with Pixel-wise Adaptive Filters

【论文精读】ISBI 2022 - Retinal Vessel Segmentation with Pixel-wise Adaptive Filters 【论文原文】&#xff1a;Retinal Vessel Segmentation with Pixel-wise Adaptive Filters 【作者信息】&#xff1a;Li, Mingxing and Zhou, Shenglong and Chen, Chang and Zhang, …