C++类库开发详解

2023-05-16

前言:这是一篇总结性的文章,需要有一点C++和dll基本知识的基础,在网上查阅了很多资料感觉没有一篇详细、具体、全面的dll开发介绍,我这是根据最近项目和网上资料整理出来的,并附带实例的一个总结性的文章(由于篇幅较长故不附带源码解释)。另外,个人愚昧地认为以后C++的开发会更多地面向库的开发,所以学会库的开发必不可少。

 

1、 静态链接库和动态链接库

1.   静态链接库(LIB)只用在程序开发期间使用,而动态链接库(DLL)在执行期间使用。

2.   静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。

3.   静态链接库,浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。另一个问题是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库libname.lib更新了,所有使用它的应用程序都需要重新编译、发布给用户(对于用户来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。

4.   动态库则实现了增量更新,进程间可以共享动态库,节约了资源,当程序第一次调用动态库时,系统将该库加载到内存中,当另一个程序也调用这个库时,系统不再加载,而是将状态+1,当某个程序退出或释放该库时,状态则-1,直到当系统中没有程序调用该库时,系统自动将其清理并释放内存。

 

2、 知识点

1.   在VS中创建的类库有2种类型,一种是直接选择VC++类库(是使用微软版本的C++创建的类库),一种是Win32项目或Win32控制台程序,然后选择对应的类库类型,也就是ANSI标准的C++类库,一般我们用这种方式创建的类库,而它又分三种:Non-MFC DLL(非MFC动态库)、MFC Regular DLL(MFC规则DLL)、MFC ExtensionDLL(MFC扩展DLL)。

2.   非MFC动态库不采用MFC类库结构,其导出函数为标准的C接口,能被非MFC或MFC编写的应用程序所调用;MFC规则DLL包含一个继承自CWinApp的类,但其无消息循环;MFC扩展DLL采用MFC的动态链接版本创建,它只能被用MFC类库所编写的应用程序所调用。

3.   当Windows要执行一个使用了动态链接库的程序而需要加载该链接库时,动态链接库文件必须储存在含有该.EXE程序的目录下、目前的目录下、Windows系统目录下、Windows目录下,或者是在通过MS-DOS环境中的PATH可以存取到的目录下(Windows会按顺序搜索这些目录)。

4.   动态链接库模块可能有其它扩展名(如.EXE或.FON),但标准扩展名是.DLL。只有带.DLL扩展名的动态链接库才能被Windows自动加载。如果文件有其它扩展名,则程序必须另外使用LoadLibrary或者LoadLibraryEx函数加载该模块。

5.   DLL 的编制与具体的编程语言及编译器无关。只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用。

 

3、 关键字

1.   当建立一个DLL时,它应该包含处理字符和字符串的Unicode和非Unicode版的所有函数,比如实现ANSI版和宽字符版。

#ifdef UNICODE
#define TextW  //定义宽字符版的函数
#else
#define TextA  //定义ANSI版的函数
#endif

 

2.  __declspec(dllexport),该关键字位于类/函数的声明和定义中,表示该类/函数为DLL的导出类/函数。而DLL内的类/函数分两种,一种是DLL导出类/函数供外部程序调用,一种是DLL内部函数供DLL自己调用。

3.  __declspec(dllimport),该关键字说明类/函数为导入函数,与__declspec(dllexport)匹配对应,为了在应用程序中使用其声明的类/函数。

 

4.  extern"C",是为了解决导出函数名的问题,因为C++编译器,为实现函数重载,在编译生成的汇编代码中要对函数名进行一些处理,而用 extern "C"声明的函数将使用函数名作符号名,这时C的处理方式。因此,只有非成员函数才能被声明为extern "C",并且不能被重载。但是,冠以extern "C"限定符后,并不意味着函数中无法使用C++代码了,相反,它仍然是一个完全的C++函数,可以使用任何C++特性和各种类型的参数。但这只解决了C/C++之间调用的问题,更可靠的方法是定义一个.def文件。

5.  __cplusplus,是cpp中自定义宏,定义了这个宏表示它是一段cpp的代码。并且这是一个C++编译器保留的宏定义,意味着C++编译器认为这个宏已经定义了。

如果函数这样定义:extern”C” int add(int a, int b);由于C编译器不能识别extern”C”指令,那么C调用C++程序就会出现问题,这时候__cplusplus就起作用了。如下:

#ifdef __cplusplus
extern "C" {
#endif

//....声明代码

#ifdef __cplusplus
}
#endif


6.  #pragma comment( lib , "..//debug//LIBProject.lib" )的意思是指本文件(应用程序)生成的.obj文件应与LIBProject.lib一起连接。

7.  __stdcall,它是Standard Call的缩写,是C的标准函数调用方式:所有参数从右到左依次入栈,如果调用的是类成员的话,最后一个入栈的是this指针。堆栈中的参数由被调用的函数在返回后清除,函数在编译的时候就必须严格控制参数生成,否则返回后会出错。

8.  __fastcall,是编译器指定的快速调用方式。由于使用堆栈传递比较费时,因此__fastcall通常规定将前N(一般2个,不同的编译器规定使用的寄存器个数不同)个参数由CPU寄存器传递,其余的还是用内存的堆栈传递。返回方式和__stdcall相当。由于其涉及到编译器决定参数传递方式,故不能作为跨编译器的接口。

 

9.  __cdecl,它是C Declaration的缩写,表示C语言默认的函数调用方式:所有的参数从右到左依次入栈,参数由调用者清除(手动清除,调用者一般指编译器)。特点在于可以使用不定个数的参数。

 

如果通过VC++编写的DLL欲被其他语言编写的程序调用,应将函数的调用方式声明为__stdcall方式,而C/C++缺省的调用方式却为__cdecl(默认调用方式)。__stdcall与__cdecl的区别在于生成函数名最终符号的方式不同。若采用C编译方式(在C++中将函数声明为extern "C"),__stdcall约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数,形如_functionname@number;而__cdecl约定仅在输出函数名前面加下划线,形如_functionname。

注意,声明函数形式:extern “C” int __stdcall add(int x, int y);,应用程序中定义函数指针为:typedef int(__stdcall *lpAddFun)(int, int);

 

4、 静态库(lib/a)

由于静态库是跟随着应用程序一起编译连接到源文件(exe)的,所以代码写法基本没有特殊的地方,需要注意的是extern"C"来确定是否使用C的方式编译,然后就是利用#ifndef来管理一类型的类/函数的调用。

值得注意的是在应用程序中使用静态库时的声明#include"MathTool.h"、#pragma comment(lib,"LIBProject.lib"):直接将.h和.lib文件放在当前目录似乎是不行的(我测试时不行的),两种方法:1.使用相对路径或绝对路径包含.h和.lib文件。2.通过”属性”--”C/C++” --“常规”--”附加包含目录”,来指定.h的文件目录。通过”属性”--”链接器” -- “常规”--”附加库目录”,来添加.lib目录。这种方法动态库也适用。

如果不想用#pragmacomment来指定lib,还可以在”属性”--”链接器” -- “常规”--”附加依赖库”来指定库。也可以不设置库目录和依赖库名,而是直接“属性”--“链接器”--”命令行”,输入静态库的完整路径即可。但一般不推荐。

示例见:LIBProject。

 

5、 动态库(dll/so)

1.  动态库的lib文件和静态库的lib文件

静态库对应的lib文件叫静态库,动态库对应的lib文件叫导入库。实际上静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

 

2.  声明导出函数(介绍.def)

DLL导出函数的声明有两种方式:一种是在声明中加__declspec(dllexport); 一种是采用模块定义(.def) 文件声明。.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。

.def文件的规则为:

(1)LIBRARY语句说明.def文件相应的DLL;

 (2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

(3).def 文件中的注释由每个注释行开始处的分号(;) 指定,且注释不能与语句共享一行。

GetInstance = GetInstance这样可以指定了DLL的函数导出后的名称仍然不变。

注:使用了.def文件记得在编译器:”属性”--”链接器”--”输入”--”模块定义文件”中设置改def文件。

如果使用__declspec(dllexport)的方式声明导出,在C++中使用当然没有问题,但是当其他语言(C#、VB)调用时,就会出现找不到函数名的情况,是因为C++中为实现重载机制将函数名改变了,这时我们为了能够让其他语言正确的调用,就要使用extern “C”+ __declspec(dllexport)+__stdcall的方式。而使用def文件这些都可以不要,这样更方便,但是用到类的地方还是要用第一种方式。

 

3.  调用方式

DLL的调用方式也有两种:一种是动态调用;一种是静态调用。

动态调用:它完全由编程者用 API 函数加载和卸载 DLL,程序员可以决定 DLL文件何时加载或不加载,显式链接在运行时决定加载哪个 DLL文件。由LoadLibrary->GetProcAddress->FreeLibrary系统API提供的三位一体“DLL加载-DLL函数地址获取-DLL释放”方式。

动态调用注意的地方,在函数前面加extern “C”或定义def文件。显式调用类库中的class是很危险和繁琐的,因此能隐式不显式,能静态不动态

静态调用: 它的特点是由编译系统完成对DLL的加载和应用程序结束时 DLL 的卸载。静态调用方式的当调用某DLL的应用程序结束时,若系统中还有其它程序使用该 DLL,则Windows对DLL的应用记录减1,直到所有使用该DLL的程序都结束时才释放它。当程序员通过静态链接方式编译生成应用程序时,应用程序中调用的与.lib文件中导出符号相匹配的函数符号将进入到生成的EXE 文件中,.lib文件中所包含的与之对应的DLL文件的文件名也被编译器存储在 EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows将根据这些信息发现并加载DLL,然后通过符号名实现对DLL 函数的动态链接。这样,EXE将能直接通过函数名调用DLL的输出函数,就像调用程序内部的其他函数一样。静态调用方式简单实用,但不如动态调用方式灵活。

静态调用需要两步:

1.  告诉编译器与DLL相对应的.lib文件所在的路径及文件名, #pragma comment(lib,"dllTest.lib")。程序员在建立一个DLL文件时,连接器会自动为其生成一个对应的.lib文件,该文件包含了DLL 导出函数的符号名及序号(并不含有实际的代码)。在应用程序里,.lib文件将作为DLL的替代文件参与编译。具体可以这样做,将.h、.lib、.dll文件拷贝到客户端程序当前目录下,然后在程序中#include<*.h> + #pragmacomment(lib,"dllTest.lib");或者在客户端程序的工程属性里面增加对该lib文件的引入。

2.  声明导入函数, 用__declspec(dllimport)说明为导入函数。有时是不用声明的,在类库的编写过程中定义好了。

 

4.  DllMain函数

Windows在加载DLL的时候,需要一个入口函数,就如同控制台或DOS程序需要main函数、WIN32程序需要WinMain函数一样。当程序中没有写DllMain函数时,系统会从其它运行库中引入一个不做任何操作的缺省DllMain函数版本,并不是DLL可以放弃DllMain函数。

根据编写规范,Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据,它使得DLL得以保留在内存里。这个函数并不属于导出函数,而是DLL的内部函数。这意味着不能直接在应用程序中引用DllMain函数,DllMain是自动被调用的。

DllMain函数在DLL被加载和卸载时被调用,在单个线程启动和终止时,DLLMain函数也被调用,ul_reason_for_call指明了被调用的原因。

 

BOOL APIENTRY DllMain( HMODULEhModule,
                      DWORD ul_reason_for_call,
                      LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

解析:

APIENTRY被定义为__stdcall,它意味着这个函数以标准Pascal的方式进行调用,也就是WINAPI方式;

ul_reason_for_call的四个参数DLL_PROCESS_ATTACH表示进程调用;DLL_THREAD_ATTACH表示线程调用;DLL_THREAD_DETACH线程释放;DLL_PROCESS_DETACH线程释放。

lpReserved是一个保留字,基本没有什么作用,无需了解。

进程中的每个DLL模块被全局唯一的32字节的HINSTANCE句柄标识,只有在特定的进程内部有效,句柄代表了DLL模块在进程虚拟空间中的起始地址。在Win32中,HINSTANCE和HMODULE的值是相同的,这两种类型可以替换使用,这就是函数参数hModule的来历。

GetProcAddress( hDll, MAKEINTRESOURCE ( 1 ) )要注意,它直接通过.def文件中为add函数指定的顺序号访问add函数,具体体现在MAKEINTRESOURCE ( 1 ),MAKEINTRESOURCE是一个通过序号获取函数名的宏,定义为(节选自winuser.h):

#defineMAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))
#defineMAKEINTRESOURCEW(i) (LPWSTR)((DWORD)((WORD)(i)))
#ifdef UNICODE
#defineMAKEINTRESOURCE MAKEINTRESOURCEW
#else
#defineMAKEINTRESOURCE MAKEINTRESOURCEA


5.  DLL导出变量

DLL定义的全局变量可以被调用进程访问;DLL也可以访问调用进程的全局数据。步骤:

1.  库的头文件.h中声明,extern int dllGlobalVar;

2.  在.cpp文件中声明使用,声明:int dllGlobalVar;使用:dllGlobalVar = 100;

3.  .def文件中导出,”GlobalVar_a@[n]”的方式,有人说是dllGlobalVar CONSTANT(已过时)/ dllGlobalVar DATA这个方式,但是我用的不行。

4.  在应用程序中引用DLL中定义的全局变量,方式有两种:一种方法(使用def声明的变量):首先声明extern int dllGlobalVar;然后int a = *(int*)dllGlobalVar。 特别要注意的是用externint dllGlobalVar声明所导入的并不是DLL中全局变量本身,而是其地址。另一种方法:externint _declspec(dllimport) dllGlobalVar; 通过_declspec(dllimport)方式导入的就是DLL中全局变量本身而不再是其地址了。建议第二种方式,第一种方式我测试中遇到一些很奇怪的问题。希望,有人根据我的测试,帮我解决下。

示例见:DLLProjec

 

6.  DLL导出类

导出类,我们一般使用静态调用,这样我们可以将整个类导出,或者只将类中的指定成员导出。如果使用动态调用类,我们一般使用一个全局函数来返回一个类的对象。

最后,学习到这里,最大的领悟就是,类库的编写,主要理解extern”C”、_declspec(dllexport)、_declspec(dllimport)、__stdcall、__cdecl这几个基本关键字,类库是提供给别人用的,我需要做的就是指定将哪些类或函数指定为用户使用的。还有就是使用类库,知道静态调用和动态调用的方法。

示例见:DLLProjec

 附源码链接:http://download.csdn.net/detail/z702143700/8738467

后记:本文很长,也是我花费了很多个工作日学习实践的成果,如果有错误或意见希望能给我留言,结合示例来看会更加好些,如果可以直接看懂示例,那么长的文字也就可以随便浏览了。接下来,我会介绍其他语言调用C++类库常用的方法(C#调用C++的库)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++类库开发详解 的相关文章

  • 5.7 属性声明

    5 7 属性声明 主要用途 使用 attribute 来声明变量 函数的特殊属性 指导编译器来进行特定方面的优化或代码检查 使用方法 在声明后面添加 xff1a attribute ATTRIBUTE 例 xff1a int global
  • 8.18 模块设计原则:高内聚低耦合

    8 18 模块设计原则 xff1a 高内聚低耦合 模块内聚 定义 xff08 软考 xff09 块内联系 xff1a 模块内各元素的关联 交互程度 从功能角度 xff1a 自己的功能自己实现 xff0c 不麻烦其它模块 如何实现高内聚 功能
  • 9.12 中断(下):中断函数的编写

    9 12 中断 下 xff1a 中断函数的编写 中断特性 可随时打断正在执行的任务 可在任何地方打断正在执行的任务 中断返回后 xff0c CPU不一定重新执行被打断的任务 中断函数 调用时间不固定 xff1a 中断要自己保护现场 调用地点
  • 9.16 内存、外存与外设

    9 16 内存 外存与外设 按速度排列 寄存 缓存 内存 外存 存储分类 内存 又称主存 xff1a CPU能直接寻址的存储空间 存取速度快 包括 xff1a RAM ROM cache等 外存 又称辅存 xff1a 除CPU缓存和内存以外
  • 载波相位测量原理

    1 重建载波 定义 xff1a 载波调制了电文之后变成了非连续的波 xff0c 将非连续的载波信号恢复成连续的载波信号 码相关法 xff1a 方法 将所接收到的调制信号 xff08 卫星信号 xff09 与接收机产生的复制码相乘 技术要点
  • wpa_suplicant 详解 文章收集

    wpa suplicant 详解 文章收集 参考资料 https w1 fi wpa supplicant devel index html https zhuanlan zhihu com p 24246712 https www cnb
  • 玩转AOSP源码编译

    整理搬运一下大佬的文章 https www bilibili com video BV19f4y1r7E6 http liuwangshu cn batcoder aosp 3 compiling aosp html 1 前言 1 1 re
  • Qt 64位链接 mysql8.0 中出现的问题及其解决办法

    1 driver not loaded 原因总结 MinGW编译器中找不到 MySql驱动或者驱动位数不对MinGW编译器找不到 MySql动态库或者动态库有问题代码写的有问题 https blog csdn net l0p0c artic
  • Linux man 手册中各种括号的含义

    尖括号 lt gt 一般用于表示必选项或者参数的占位符 xff0c 实际使用时需要替换成具体的值 方括号 一般用于表示可选项或者参数的占位符 xff0c 实际使用时可以选择是否包含该选项或者参数 大括号 一般用于表示一组选项或者参数 xff
  • 批量创建 markdown 文件的脚本

    写一个 dos脚本 xff0c 其功能是创建 36 个 以 34 Linux内核编程 ch11 sec 34 为开头的 Markdown格式的文件 64 echo off chcp 65001 setlocal enabledelayede
  • libcurl库的http get和http post使用

    一 libcurl中的http get使用方法 1 为什么要使用libcurl 1 作为http的客户端 xff0c 可以直接用socket连接服务器 xff0c 然后对到的数据进行http解析 xff0c 但要分析协议头 xff0c 实现
  • Postman查看完整的请求报文

    第一步 工具栏 View gt Show postman console 第二步 点击 Show Postman Console 之后 就会弹出一个如下图所示的界面 小窍门 postman可以把请求的参数生成代码 可以在代码使用 仅仅只需点
  • 通用异步接收器/发送器(UART)——发送与接收

    图1 带数据总线的UART UART代表通用异步接收器 发送器 它不是像SPI和I2C这样的通信协议 xff0c 而是微控制器中的物理电路或独立的IC UART的主要目的是发送和接收串行数据 关于UART最好的一点是其仅使用两条线在设备之间
  • MYSQL导入数据出现Error 1290:The MySQL server is running with the --secure-file-priv option so it cannot ex

    最近在学习MySQL xff0c 刚入门 xff0c 在导入数据的时候出现了Error 1290 xff1a The MySQL server is running with the secure file priv option so i
  • openmv--无人机通过mavlink实现apriltag定点降落

    span class token comment 无人机通过mavlink实现apriltag定点降落例程 span span class token comment span span class token comment 这个脚本使用
  • [转] 用WWW-Authenticate实现登录验证

    用WWW Authenticate实现登录验证 文章来源 xff1a http www keakon cn bbs thread 1989 1 1 html 今天在研究HTTP协议时发现一个叫WWW Authenticate的头字段 xff
  • ROS--坐标理解

    北东地坐标系 NED north east down 东北天 ENU east north up 机体坐标系 body frame 载体坐标系 是以载体为中心 xff0c 主要作用是处理与传感器直接测得的物理量 导航坐标系 可以是地固坐标系
  • qt 编译qgc常见问题

    qt LINK warning LNK4098 默认库 MSVCRT 与其他库的使用冲突 xff1b 请使用 NODEFAU 如果以前没有问题 xff0c 突然出现的这个问题 xff0c 绝大可能是中间编译过程太多造成的 清理项目 重新构建
  • VINS-FUSION-GPU在jetson nx上的实现

    需要安装经过修改的Ubuntu18系统 https span class token operator span span class token comment developer nvidia com zh cn embedded do
  • 主机ping通虚拟机,虚拟机ping通主机解决方法(NAT模式)

    主机ping通虚拟机 xff0c 虚拟机ping通主机解决方法 xff08 NAT模式 xff09 有时候需要用虚拟机和宿主机模拟做数据交互 xff0c ping不通是件很烦人的事 xff0c 本文以net模式解决这一问题 宿主机系统 xf

随机推荐

  • 一个基于Matlab的简单Gui设计

    前几日浩子说要编一个基于Matlab的用户图像界面 xff0c 他用GUIDE搭了一个大概的框架 xff0c 大概要实现数据读入 做图分析 图像清除 关闭界面的功能 xff0c 我用函数形式给改编了一个 xff0c 虽然问题比较简单 xff
  • 关于N步相移中相位噪声仿真分析的一点说明

    在条纹投影的三维测量中 xff0c 有这么一个经典的结论 xff1a 假设光强的噪声为方差为 2 xff0c 那么 xff0c 经过N步标准相移求得的相位的方差为2 2 N B 2 xff08 xff09 xff0c 其中 xff0c B为
  • 如何给MFC对话框添加背景图片

    一 创建项目 文件 新建项目 MFC应用程序 该页面使用 基于对话框 完成即可 注意 取消 使用Unicode库 否则在使用AfxMessageBox会报错 xff0c 没有一个可以转换的参数类型 xff0c 要加AfxMessageBox
  • 如何检测应用程序调用了哪些DLL文件?

    之前所用的检测工具是Dllshow xff0c 后来突然不能用了 xff0c VS以前有Depends xff0c 后来高级版本也没了 最近找到一种简单方便的方法 xff0c 利用windowsx系统自带的功能 运行你想知道的应用程序 xf
  • 网络编程懒人入门(一):快速理解网络通信协议(上篇)

    1 写在前面 论坛和群里常会有技术同行打算自已开发IM或者消息推送系统 xff0c 很多时候连基本的网络编程理论 xff08 如网络协议等 xff09 都不了解 xff0c 就贸然定方案 写代码 xff0c 显得非常盲目且充满技术风险 即时
  • Matlab中调用C++dll

    利用mex技术可以实现这个功能 xff0c 但是必须例外写一个接口函数 xff0c 比较麻烦 利用dll调用的方法 xff0c 简单方便 下面就以实现加法函数add 为例 xff0c 来详细介绍具体过程 一 利用VS生成dll文件 利用VS
  • 大小端序与端序转换

    最近在做客户项目的时候 xff0c 遇到了不同厂家的安防相机输出的数据大小端序不一致的情况 xff0c 导致在使用同一种方式处理时 xff0c 出现了错误 虽然问题已经解决 xff0c 还是顺手把大小端序的知识简单梳理一下 1 大端序和小端
  • debian ware source

    deb http ftp cn debian org debian jessie main non free contrib deb http ftp cn debian org debian jessie proposed updates
  • debian中文输入法——拼音和五笔的解决方法

    最近安装Debian操作系统 xff0c 但遇到一个重大的困惑 xff0c 那就是为什么Debian菜单里面有一个Fcitx的选项 xff0c 但是为什么就是无法调出前端来实现输入 xff0c 这是个大问题 xff0c 于是就研究 xff0
  • YOLOv5图像分割中的NMS处理

    在上一篇文章YOLOv5图像分割 SegmentationModel类代码详解有讲到图像经过YOLOv5网络后得到的输出形式 xff0c 主要是调用了BaseModel类下的forward得到的输出 xff0c 输出的shape为 batc
  • YOLO之trt推理+Diou/iou目标跟踪以及计数【附代码】

    本篇文章是对之前YOLOv4 tensorrt推理项目的更新 xff0c 在trt推理 xff0c 多进程语音报警的功能中又新添加了目标跟踪 可用于目标计数 采用IOU进行跟踪 也可以选用DIOU yolov4 43 deepsort可以参
  • yolov5_reid【附代码,行人重识别,可做跨视频人员检测】

    该项目利用yolov5 43 reid实现的行人重识别功能 xff0c 可做跨视频人员检测 应用场景 xff1a 可根据行人的穿着 体貌等特征在视频中进行检索 xff0c 可以把这个人在各个不同摄像头出现时检测出来 可应用于犯罪嫌疑人检索
  • src目录和项目路径的联系

    code src目录里面的东西会被eclipse编译 xff0c 编译完了就放到了 bin目录下 xff0c 而bin目录就是我们项目的classPath code
  • 逆向加固分析

    34 libsecexe so 34 34 梆梆加固免费版 34 34 libsecmain so 34 34 梆梆加固免费版 34 34 libSecShell so 34 34 梆梆加固免费版 34 34 secData0 jar 34
  • android之visibility的三个属性

    android visibility 61 34 34 其有三个属性 xff1a visible显示 xff1b invisible显示黑背景条 xff0c 在这种情况下它会占据空间 xff1b gone不显示 在类中 xff0c 可以设置
  • android中的Application类

    在2011年做的一个iptv项目中就接触了这个Application类 xff0c 虽用起来简单 xff0c 但还是有些需要注意的地方 空闲之余 xff0c 总结如下 xff1a android 系统为每个程序运行时创建一个Applicat
  • android混淆

    首先要说的话 xff1a 本文是对好几个博文的摘录再加上我自己的理解 xff0c 以尊重原创为原则 xff0c 下面贴出相关博文的链接 Android有效地减少方法数 http blog csdn net lihenair article
  • ROS通信

    1 话题通信 话题通信是ROS中使用频率最高的一种通信模式 xff0c 话题通信是基于发布订阅模式的 xff0c 也即 一个节点发布消息 xff0c 另一个节点订阅该消息 用于不断更新的 少逻辑处理的数据传输场景 ROS Master 管理
  • 解决C&C++头文件互相包含问题

    案例说明 xff1a test1中需要调用test2中的go test2 xff0c test2中需要调用test1中的go test1 main cpp span class token macro property span class
  • C++类库开发详解

    前言 xff1a 这是一篇总结性的文章 xff0c 需要有一点C 43 43 和dll基本知识的基础 xff0c 在网上查阅了很多资料感觉没有一篇详细 具体 全面的dll开发介绍 xff0c 我这是根据最近项目和网上资料整理出来的 xff0