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


int my_main()                  // called by main()
{
    Tracer tr("my_main ");      // for tracking exceptions

    // declare a matrix
    Matrix X(4, 4);

    // load values row by row
    X.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 matrix
    cout << "Matrix X" << endl;
    cout << setw(15) << setprecision(8) << X << endl;

    // calculate its inverse and print it
    Matrix 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;
#endif


int 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 matrix
    Matrix X(4, 4);

    // load values row by row
    X.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 matrix
    cout << "Matrix X" << endl;
    cout << setw(15) << setprecision(8) << X << endl;

    // calculate its inverse and print it
    Matrix 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++ 静态库和动态库的创建和使用及区别
  • 动态链接库和静态链接库的区别

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5G智慧地铁数字孪生可视化平台,推进铁路行业数字化转型

随着科技的快速发展&#xff0c;5G智慧地铁数字孪生可视化平台正逐渐成为铁路行业数字化转型的重要推动力。巨蟹数科数字孪生平台集成了5G通信技术、大数据分析、云计算和人工智能等先进技术&#xff0c;通过构建数字孪生模型&#xff0c;实现对地铁运营全过程的实时监控、预测…

rocketmq的运维

1. admintool创建topic的时候 -o 的用法含义 https://rocketmq.apache.org/zh/docs/4.x/producer/03message2/ 有关orderMessageEnable和returnOrderTopicConfigToBroker的设置可以参考 https://blog.csdn.net/sdaujsj1/article/details/115741572 -c configFile通过-c命令指…

大模型prompt技巧——思维链(Chain-of-Thought)

1、Zero-shot、One-shot、Few-shot 与fintune prompt的时候给出例子答案&#xff0c;然后再让模型回答。 2、zero-shot-CoT “Let’s think step by step”有奇迹效果 3、多数投票提高CoT性能——自洽性&#xff08;Self-consistency&#xff09; 多个思维链&#xff0c;然后取…

【深度学习】sdwebui的token_counter,update_token_counter,如何超出77个token的限制?对提示词加权的底层实现

文章目录 前言关于token_counter关于class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing)如何超出77个token的限制&#xff1f;对提示词加权的底层实现Overcoming the 77 token limit in diffusers方法1 手动拼方法2 compel 问询、帮助请看&#xff1a; 前言 …

跟着Kimi Chat学习提示工程Prompt Engineering!让AI更高效地给你打工!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

【JavaWeb】百度地图API SDK导入

百度地图开放平台 | 百度地图API SDK | 地图开发 (baidu.com) 登录注册&#xff0c;创建应用&#xff0c;获取AK 地理编码 | 百度地图API SDK (baidu.com) 需要的接口一&#xff1a;获取店铺/用户 所在地址的经纬度坐标 轻量级路线规划 | 百度地图API SDK (baidu.com) 需要的…

Fastjson 1.2.47 远程命令执行漏洞复现分析环境

Fastjson 1.2.47 远程命令执行漏洞 1、靶机环境安装 1.1、虚机机linux环境参数 1、操作系统&#xff1a;CentOS Linux release 7.4.1708 (Core) 2、IP&#xff1a;192.168.127.1321.1、docker与docker compose安装 1.2、下载https://github.com/vulhub/vulhub/tree/master/…

Golang | Leetcode Golang题解之第8题字符串转换整数atoi

题目&#xff1a; 题解&#xff1a; func myAtoi(s string) int {abs, sign, i, n : 0, 1, 0, len(s)//丢弃无用的前导空格for i < n && s[i] {i}//标记正负号if i < n {if s[i] - {sign -1i} else if s[i] {sign 1i}}for i < n && s[i] >…

java数据结构与算法刷题-----LeetCode417. 太平洋大西洋水流问题

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 深度优先遍历 深度优先遍历 解题思路&#xff1a;时间复杂度O( …

【计算机视觉】四篇基于Gaussian Splatting的SLAM论文对比

本文对比四篇论文&#xff1a; [1] Gaussian Splatting SLAM [2] SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM [3] Gaussian-SLAM: Photo-realistic Dense SLAM with Gaussian Splatting [4] GS-SLAM: Dense Visual SLAM with 3D Gaussian Splatting …

RTX RTOS 操作实例分析之---线程(thread)

0 Preface/Foreword 1 线程&#xff08;thread&#xff09; 1.1 线程定义 1.1.1 USE_BASIC_THREADS&#xff08;宏定义&#xff09; 经过以上步骤&#xff08;makefile包含&#xff09;&#xff0c;USE_BASIC_THREADS在编译阶段被定义到相应的模块中。 1.1.2 定义线程ID变量…

element-ui collapse 组件源码分享

今日简单分享 collapse 组件的源码实现&#xff0c;主要分为四个方面&#xff1a; 1、collapse 组件页面结构 2、collapse 组件属性 3、collapse 组件事件 4、collapse item 组件属性 一、collapse 组件页面结构 二、collapse 组件属性 2.1 value/v-model 属性&#xff0…

Linux终端人性化vimrc编辑配置

目录 vim常用操作 扩展之批量注释 扩展之批量替换 .vimrc pyhon代码补全功能安装 效果预览 .bashrc 终端命令行预览时间 vim常用操作 常用的操作有很多&#xff0c;基本上总会用到的例如 x 删除当前字母 dd 删除正行 i 当前光标插入数据 a 当前位置后插入数据 …

安装Schedule库的方法最终解答!_Python第三方库

安装Python第三方库Schedule 我的环境&#xff1a;Window10&#xff0c;Python3.7&#xff0c;Anaconda3&#xff0c;Pycharm2023.1.3 Schedule库 Schedule 是一个轻量级、功能强大而灵活的任务调度工具库&#xff0c;用于在指定的时间间隔内执行任务。为用户提供了简单易用的…

标题:探索AI绘画:使用深度学习生成艺术

正文&#xff1a; 随着计算机技术的发展&#xff0c;人工智能在各个领域取得了显著的成果。通过训练深度学习模型&#xff0c;AI可以学习大量的艺术作品&#xff0c;从而生成具有独特风格和创意的新作品。 本文将介绍如何使用Python和TensorFlow实现一个简单的AI绘画程序。 二、…

云原生:应用敏捷,华为视角下的应用现代化

Gartner 也提出&#xff0c;到 2023 年&#xff0c;新应用新服务的数量将达到 5 亿&#xff0c;也即是说&#xff1a;“每个企业都正在成为软件企业”。据IDC 预测&#xff0c;到 2025 年三分之二的企业将成为多产的“软件企业”&#xff0c;每天都会发布软件版本。越来越多的企…

AI绘图:Stable Diffusion WEB UI 详细操作介绍:基础篇

接上一篇《AI绘图体验&#xff1a;Stable Diffusion本地化部署详细步骤》本地部署完了SD后&#xff0c;大家肯定想知道怎么用&#xff0c;接下来补一篇Stable Diffusion WEB UI 详细操作&#xff0c;如果大家还没有完成SD的部署&#xff0c;请参考上一篇文章进行本地化的部署。…

vue2+element-ui 实现OSS分片上传+取消上传

遇到问题&#xff1a;项目中需要上传500MB以上的视频。一开始使用上传组件el-upload&#xff0c;调用后台接口&#xff0c;但是出现了onprogress显示百分百后接口一直pending&#xff0c;过了很多秒后接口才通&#xff0c;如果遇到大文件的话&#xff0c;接口就会报超时。 解决…

【javaScript】DOM编程入门

一、什么是DOM编程 概念&#xff1a;DOM(Document Object Model)编程就是使用document对象的API完成对网页HTML文档进行动态修改&#xff0c;以实现网页数据和样式动态变化的编程 为什么要由DOM编程来动态修改呢&#xff1f;我们就得先理解网页的运行原理&#xff1a; 如上图&a…

机器学习每周挑战——信用卡申请用户数据分析

数据集的截图 # 字段 说明 # Ind_ID 客户ID # Gender 性别信息 # Car_owner 是否有车 # Propert_owner 是否有房产 # Children 子女数量 # Annual_income 年收入 # Type_Income 收入类型 # Education 教育程度 # Marital_status 婚姻状况 # Housing_type 居住…