C++ 静态库与动态库的生成和使用:基于 VS Studio 生成 newmat 矩阵库的静态库与动态库

文章目录

  • Part.I Introduction
    • Chap.I 预备知识
    • Chap.II 静态库与动态库区分
  • Part.II 静态库的生成与使用 (newmat)
    • Chap.I 生成静态库
    • Chap.II 使用静态库
  • Part.III 动态库的生成与使用 (newmat)
    • Chap.I 生成动态库
    • Chap.II 使用动态库
  • Part.IV 文件内容
    • Chap.I test.cpp (静态库)
    • Chap.II test.cpp (动态库)
    • Chap.III 测试文件下载
  • Reference

Part.I Introduction

本文将详细地介绍 C++ 动态库和静态库,尽量让读者对他们有一个明晰的区分。然后基于一个实例(newmat 矩阵库)进行实际操作,以加深印象。

在这里插入图片描述

Chap.I 预备知识

在阅读下面的内容之前,首先需要了解如下概念和信息:

  • 动态链接库(Dynamic Link Library)或叫共享库(Shared Object)(这就是 dllso 文件后缀的由来)
  • 静态链接库(Static Link Library

有关库的一些文件

  • *.h 文件:C++ 头文件(文本文件),一般会包含函数的声明。
  • *.lib 文件:库文件(二进制文件),它可能是完整的静态库,里面有函数代码本身,在编译时直接将代码加入程序当中,应用程序直接使用;也有可能是动态库的导出声明,只包含头部信息。里面只有函数所在的 DLL 文件和文件中函数位置的入口,代码由运行时加载在进程空间中的 DLL 提供
  • *.dll 文件:动态库文件(二进制文件),Windows 下的动态库文件。
  • *.a 文件:UNIX 下的静态库文件
  • *.so 文件:UNIX 下的动态库文件

Chap.II 静态库与动态库区分

我们写程序的时候会需要加载库,一般需要先include头文件,然后再调用库函数,而库又分为两种,静态库(lib)和动态库(dll),那么这两种库有什么区别呢?

  • 静态库:我们的程序在链接时会把用到的静态库全部都链接进去,形成一个exe,这也导致我们的exe很大(程序是先编译,再链接库,最后形成exe
  • 动态库:程序在链接时在不再把整个库都链接进去,而是程序在运行过程中,用到哪个库,再加载哪个库,这就降低了exe的大小,但同时,运行速度也会变慢。

动态库与静态库优缺点分析
动态链接库优点 包括可减少程序的磁盘空间占用、方便更新库文件、共享库文件、提高程序间的互操作性、降低内存占用;缺点 包括需要确保运行环境中库文件的可用性。
静态链接库优点 包括编译后的可执行文件相对独立、移植性好、提高程序运行速度;缺点 包括每个可执行文件都包含一份静态库的拷贝、需要手动更新库文件。


静态链接库的使用

需要的文件:

  • *.h :头文件*.h中有函数的声明,使用静态链接库的项目需要引用(#include)文件才能编译通过
  • *.lib:包含了实际执行代码、符号表等等

加载*.lib的方法:

  • 用编译链接参数或者 VS 的配置属性来设置
  • 使用 pragma 编译语句,例如 pragma comment(lib,"a.lib")

动态链接库的使用——隐式调用

需要的文件

  • *.h :头文件*.h中有函数的声明,使用静态链接库的项目需要引用(#include)文件才能编译通过
  • *.lib:包含了函数所在的 *.dll 文件和文件中函数位置的信息。
  • *.dll:包含了实际执行代码、符号表等等

*.lib文件是『链接』时用的,加载方法同样有:

  • 用编译链接参数或者 VS 的配置属性来设置
  • 使用 pragma 编译语句,例如 pragma comment(lib,"a.lib")

*.dll文件是程序『运行』时用的,链接了lib之后形成的EXE可执行文件中已经有了dll的信息,所以只要dll放在和exe同一个目录下就可以了,运行时根据 EXE 需要自动加载dll中的函数。


动态链接库的使用——显示调用

需要的文件:只有动态链接库的 *.dll 文件,不需要*.h 文件和*.lib 文件。因为 LoadLibrary 之后可以使用 getProcAddress 来查找一个函数的地址从而调用该函数。


PS: 显式调用的前提是使用者需要知道想调用的函数的名字、参数、返回值信息,也就是说虽然编译链接用不上.h头文件,但是调用者编程时可能还是要看.h文件作参考来知道函数名字、参数、返回值信息


显式调用动态库步骤

  1. 创建一个函数指针,其指针数据类型要与调用的 DLL 引出函数相吻合。
  2. 通过 Win32 API 函数 LoadLibrary() 显式的调用 DLL,此函数返回 DLL 的实例句柄。
  3. 通过 Win32 API 函数 GetProcAddress() 获取要调用的 DLL 的函数地址,把结果赋给自定义函数的指针类型。
  4. 使用函数指针来调用 DLL 函数。
  5. 最后调用完成后,通过 Win32 API 函数 FreeLibrary() 释放DLL 函数。

下面将使用newmat矩阵库为例,基于 VS Studio 平台,详细介绍生成静态库和动态库的整个过程。newmat 戳我下载~

Part.II 静态库的生成与使用 (newmat)

Chap.I 生成静态库

1、新建一个『静态库』项目,名字取为LibNewmat_a

在这里插入图片描述

2、将默认创建的4个文件给排除掉,将 newmat 的 36 个文件复制到项目所在目录/src文件夹中。(注意x64)并将它们添加到项目中:右键项目→添加→现有项→进入srcCtrl+A全选→添加

在这里插入图片描述

3、选中项目右键→属性→C/C++→预编译头→不使用预编译头→应用→确定

在这里插入图片描述

4、选中项目右键→属性→C/C++→预处理器→预处理器定义→下拉三角编辑→加入_CRT_SECURE_NO_WARNINGS(这是针对newmat)进行的操作

在这里插入图片描述

5、快捷键 F6 生成,在x64/Debug目录下就生成了我们需要的*.lib

在这里插入图片描述

Chap.II 使用静态库

1、创建一个空项目,名字叫做test_a,添加一个cpp文件test.cpp

2、选中项目右键→属性→VC++ 目录→包含目录 把头文件所在目录贴进去;库目录把*.lib所在目录贴进去(看完下面的再决定要不要这样操作

在这里插入图片描述

PS:最好不要在这里加包含目录和库目录,这里时全局的(我是为了截一个图,懒狗一个)。下面是比较合适的操作:
包含目录(头文件所在目录):右键『属性』→『C/C++』→『常规』→『附加包含目录』
库目录(lib 文件所在目录):右键『属性』→『链接器』→『常规』→『附加库目录』

3、将Part.IV__Chap.I test.cpp的内容复制到文件test.cpp

4、快捷键F5得到运行结果

在这里插入图片描述

Part.III 动态库的生成与使用 (newmat)

Chap.I 生成动态库

1、新建一个『动态库』项目,名字取为LibNewmat_so

在这里插入图片描述

2、将默认创建的4个文件给排除掉,将 newmat 的 36 个文件复制到项目所在目录/src文件夹中。(注意x64)并将它们添加到项目中:右键项目→添加→现有项→进入srcCtrl+A全选→添加

在这里插入图片描述

3、选中项目右键→属性→C/C++→预编译头→不使用预编译头→应用→确定

在这里插入图片描述
4、选中项目右键→属性→C/C++→预处理器→预处理器定义→下拉三角编辑→加入_CRT_SECURE_NO_WARNINGS(这是针对newmat)进行的操作

在这里插入图片描述
5、快捷键 F6 生成,在x64/Debug目录下就生成了我们需要的*.dll

在这里插入图片描述

Chap.II 使用动态库

基于上面的操作我们可以看到:只生成了dll文件,没有生成lib文件,这是因为 newmat 库本身没有导出 (__declspec(dllexport)) 任何方法、类等,所以生成的 DL L不需要 lib 文件来记载导出符号。那这种情况下只能显示调用了,如何操作呢?浅试了一下,不会比较复杂的显式调用,暂时放弃。所以本小节后面的部分不必看了


1、创建一个空项目,名字叫做test_so,添加一个cpp文件test.cpp。(注意x64

在这里插入图片描述

2、将Part.IV__Chap.II test.cpp的内容复制到文件test.cpp

如何使用 dll 中的类型呢?求大佬指点!!

Part.IV 文件内容

Chap.I test.cpp (静态库)

/// \ingroup newmat
///@{/// \file nm_ex1.cpp
/// Very simple example 1.
/// Invert a 4 x 4 matrix then check the result#define WANT_STREAM       // include iostream and iomanipulators#include "newmatap.h"     // newmat advanced functions// should not be required for this example// included because it seems to help MS VC6// when you have namespace turned on#include "newmatio.h"     // newmat headers including output functions#pragma comment(lib,"LibNewmat_a.lib")
#ifdef use_namespace
using namespace RBD_LIBRARIES;
#endifint my_main()                  // called by main()
{Tracer tr("my_main ");      // for tracking exceptions// declare a matrixMatrix X(4, 4);// load values row by rowX.row(1) << 3.7 << -2.1 << 7.4 << -1.0;X.row(2) << 4.1 << 0.0 << 3.9 << 4.0;X.row(3) << -2.5 << 1.9 << -0.4 << 7.3;X.row(4) << 1.5 << 9.8 << -2.1 << 1.1;// print the matrixcout << "Matrix X" << endl;cout << setw(15) << setprecision(8) << X << endl;// calculate its inverse and print itMatrix Y = X.i();cout << "Inverse of X" << endl;cout << setw(15) << setprecision(8) << Y << endl;// multiply X by its inverse and print the result (should be near identity)cout << "X * inverse of X" << endl;cout << setw(15) << setprecision(8) << (X * Y) << endl;return 0;
}// call my_main() - use this to catch exceptions
// use macros for exception names for compatibility with simulated exceptions
int main()
{Try{ return my_main(); }Catch(BaseException) { cout << BaseException::what() << "\n"; }CatchAll{ cout << "\nProgram fails - exception generated\n\n"; }return 0;
}///@}

Chap.II test.cpp (动态库)

半成品没有跑通

/// \ingroup newmat
///@{/// \file nm_ex1.cpp
/// Very simple example 1.
/// Invert a 4 x 4 matrix then check the result#define WANT_STREAM       // include iostream and iomanipulators#include <iostream>
#include <windows.h>//#include "newmatap.h"     // newmat advanced functions
//                          // should not be required for this example
//                          // included because it seems to help MS VC6
//                          // when you have namespace turned on
//
//#include "newmatio.h"     // newmat headers including output functions#ifdef use_namespace
using namespace RBD_LIBRARIES;
#endifint my_main()                  // called by main()
{HINSTANCE hInst = LoadLibrary(L"LibNewmat_so.dll");   //加载dll库typedef void(*Sub)();//函数指针Sub PrintHello = (Sub)GetProcAddress(hInst, "PrintHello");//加载库函数Tracer tr("my_main ");      // for tracking exceptions// declare a matrixMatrix X(4, 4);// load values row by rowX.row(1) << 3.7 << -2.1 << 7.4 << -1.0;X.row(2) << 4.1 << 0.0 << 3.9 << 4.0;X.row(3) << -2.5 << 1.9 << -0.4 << 7.3;X.row(4) << 1.5 << 9.8 << -2.1 << 1.1;// print the matrixcout << "Matrix X" << endl;cout << setw(15) << setprecision(8) << X << endl;// calculate its inverse and print itMatrix Y = X.i();cout << "Inverse of X" << endl;cout << setw(15) << setprecision(8) << Y << endl;// multiply X by its inverse and print the result (should be near identity)cout << "X * inverse of X" << endl;cout << setw(15) << setprecision(8) << (X * Y) << endl;FreeLibrary(hInst);             //释放库return 0;
}// call my_main() - use this to catch exceptions
// use macros for exception names for compatibility with simulated exceptions
int main()
{Try{ return my_main(); }Catch(BaseException) { cout << BaseException::what() << "\n"; }CatchAll{ cout << "\nProgram fails - exception generated\n\n"; }return 0;}///@}

Chap.III 测试文件下载

有关上面的测试文件,笔者进行了整理并上传至 CSDN 资源,感兴趣的朋友可戳我免费下载。文件树如下:

newmat_lib_dll
├─DLL_project			
│  ├─LibNewmat_so		// 生成的动态库 dll
│  └─test_so			// 测试动态库 cpp 文件,半成品
├─LIB_project
│  ├─LibNewmat_a		// 生成的静态库 lib
│  └─test_a				// 测试静态库 cpp 文件
└─newmat_src			// newmat 库源码

Reference

  • C++ 静态库和动态库的创建和使用及区别
  • 动态链接库和静态链接库的区别

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

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

相关文章

Hadoop Yarn

首先先从Yarn开始讲起&#xff0c;Yarn是Hadoop架构的资源管理器&#xff0c;可以管理mapreduce程序的资源分配和任务调度。 Yarn主要有ResourceManager、NodeManage、ApplicationMaster&#xff0c;Container ResourceMange负责管理全局的资源 NodeManage&#xff08;NM&a…

九河云:在AWS上实现跨region VPC互联

如何跨region实现不同VPC之间的对等链接&#xff1f;九河云为您介绍AWS跨region连接方案。 说明&#xff1a;VPC-A位于弗吉尼亚region&#xff0c;VPC-B位于俄勒冈region 本文将在同一账户的弗吉尼亚和俄勒冈VPC中各启用一台EC2&#xff08;本文已提前创建好VPC、EC2等资源&am…

Spring Boot中前端通过请求接口下载后端存放的Excel模板

导出工具类 package com.yutu.garden.utils;import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import org.apache.commons.io.IOUtils; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger;…

云计算的安全需求

目录 一、概述 二、云安全服务基本能力要求 三、信息安全服务&#xff08;云计算安全类&#xff09;资质要求 3.1 概述 3.2 资质要求内容 3.2.1 组织与管理要求 3.2.2 技术能力要求 四、云安全主要合规要求 4.1 安全管理机构部门的建立 4.2 安全管理规范计划的编制 4…

C++ //练习 11.3 编写你自己的单词计数程序。

C Primer&#xff08;第5版&#xff09; 练习 11.3 练习 11.3 编写你自己的单词计数程序。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /*************************************************************************> …

2024最新AI创作系统ChatGPT源码+Ai绘画网站源码,GPTs应用、AI换脸、插件系统、GPT文档分析、GPT语音对话一站式解决方案

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

记 log4j-over-slf4j.jar AND bound slf4j-log4j12.jar jar包冲突问题

报错信息如下 SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details. Exception in thread “main” java.lan…

NineData云原生智能数据管理平台新功能发布|2024年3月版

数据库 DevOps - 大功能升级 SQL 开发早期主要提供 SQL 窗口&#xff08;IDE&#xff09;功能&#xff0c;在产品经过将近两年时间的打磨&#xff0c;新增了大量的企业级功能&#xff0c;已经服务了上万开发者&#xff0c;覆盖了数据库设计、开发、测试、变更等生命周期的功能…

神经网络与深度学习(二)

一、深度学习平台 张量&#xff08;Tensor&#xff09; 是一个物理量&#xff0c;对高维(维数 ≥ 2) 的物理量进行“量纲分析” 的一种工具。简单的可以理解为&#xff1a;一维数组称为矢量&#xff0c;二维数组为二阶张量&#xff0c;三维数组为三阶张量 计算图 用“结点”…

调用飞书获取用户Id接口成功,但是没有返回相应数据

原因&#xff1a; 该自建应用没有开放相应的数据权限。 解决办法&#xff1a; 在此处配置即可。

DETR【Transformer+目标检测】

End-to-End Object Detection with Transformers 2024 NVIDIA GTC&#xff0c;发布了地表最强的GPU B200&#xff0c;同时&#xff0c;黄仁勋对谈《Attention is All You Need》论文其中的7位作者&#xff0c;座谈的目的无非就是诉说&#xff0c;Transformer才是今天人工智能成…

【环境变量】命令行参数 | 概念 | 理解 | 命令行参数表 | bash进程

目录 四组概念 命令行参数概念&理解 查看命令函参数 命令行字符串&命令行参数表 命令行参数存在的意义 谁形成的命令行参数 父进程&子进程&数据段 bash进程 最近有点小忙&#xff0c;可能更新比较慢。 四组概念 竞争性: 系统进程数目众多&#xff0c…

构建企业级微服务平台:实现可扩展性、弹性和高效性

在软件开发的快速发展领域中&#xff0c;企业不断努力构建健壮、可扩展和高效的系统。随着微服务架构的出现&#xff0c;再加上云原生技术的应用&#xff0c;创建敏捷且具有弹性的平台的可能性是无限的。在本指南中&#xff0c;我们将深入探讨使用强大的工具和技术组合&#xf…

Python基于深度学习的人脸识别项目源码+演示视频,利用OpenCV进行人脸检测与识别 preview

​ 一、原理介绍 该人脸识别实例是一个基于深度学习和计算机视觉技术的应用&#xff0c;主要利用OpenCV和Python作为开发工具。系统采用了一系列算法和技术&#xff0c;其中包括以下几个关键步骤&#xff1a; 图像预处理&#xff1a;首先&#xff0c;对输入图像进行预处理&am…

.Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置

.Net Core/.Net6/.Net8 &#xff0c;启动配置/Program.cs 配置 没有废话&#xff0c;直接上代码调用 没有废话&#xff0c;直接上代码 /// <summary>/// 启动类/// </summary>public static class Mains{static IServiceCollection _services;static IMvcBuilder _…

Debian linux版本下运行的openmediavault网盘 千兆网卡升级万兆

一、适用场景 1、使用vmware ESXi虚拟化平台运行多种不同应用服务器时&#xff0c;其中网盘服务器采用开源的openmediavault搭建&#xff1b; 2、将老专业服务器升级千兆网为万兆网&#xff1b; 3、需要转移的数据量大的企业或用户&#xff1b; 4、从服务器到服务器的数据转移…

【群晖】NASTOOL-自动化处理影音视频工具

【群晖】NASTOOL-自动化处理影音视频 本文主要从获取、部署、使用、配置等方面进行手把手教学如何使用nastool工具进行影音视频自动化处理。从此靠别繁琐的网上各个网址找资源-下载-复制-改名-刮削等操作。 准备 DSM 7.1 &#xff08;我使用的是群晖 7.1 系统&#xff0c;不管…

实战webSocket压测(二)jmeter配置webSocket连接

背景 我们可以通过Jmeter添加插件实现webSocket脚本编写。WebSocket的插件较多&#xff0c;我选择以WebSocket Samplers by Peter Doornbosch为例来进行配置。 步骤1、WebSocket Samplers插件安装 下载地址&#xff1a;JMeter WebSocket Samplers&#xff0c;建议下载最新版本…

Termius for Mac v8.4.0激活版下载

Termius for Mac是一款功能强大的多协议远程管理软件&#xff0c;专为开发人员、系统管理员和网络专业人士设计。它支持多种远程连接协议&#xff0c;如SSH、Telnet、RDP、VNC和RFB等&#xff0c;使得用户可以轻松连接到不同类型的远程服务器和设备。 软件下载&#xff1a;Term…

智慧展览馆:基于AI智能识别技术的视频智慧监管解决方案

一、建设背景 随着科技的不断进步和社会安全需求的日益增长&#xff0c;展览馆作为展示文化、艺术和科技成果的重要场所&#xff0c;其安全监控系统的智能化升级已成为当务之急。为此&#xff0c;旭帆科技&#xff08;TSINGSEE青犀&#xff09;基于视频智能分析技术推出了展览馆…