C++学习笔记——动态库与静态库

C/C++通过LoadLibrary显示调用动态库 阅读详情

目录

0. 库技术简介

1. DLL用例示范

2. DLL的加载、卸载与多进程的数据段

3. DLL中的动态内存分配

4.为DLL添加头文件

5.在DLL中导出一个类

6. 静态库的编译

7. 动态库的手工加载

8. VC项目的静态编译

 

 

0. 库技术简介

在C/C++中可以将一种编译好的符号提供给第三方来使用,而源码是对用户不可见的,就是“库技术”。简单的来说就是“公开了技术,隐藏了代码”。库技术分为两种:动态库(Dynamic-Link Library, DLL)和静态库(Static Library)。

1. DLL用例示范

1> 创建一个简单的.dll程序

VS2015新建项目——windows控制台程序——点击dll创建完成。生成的项目中自动包含了两个头文件和三个cpp文件。

stdafx.h
targetver.h

dllmain.cpp
LibraryExercise.cpp //工程名
stdafx.cpp

检查三个cpp文件,发现dllmain.cpp中的dllMain作为项目的dll主函数,是系统运行最先进入的函数;stdafx.cpp与预编译信息有关;我们需要导出的核心算法在LibraryExercise.cpp中实现。打开LibraryExercise.cpp文件,输入以下代码:

// LibraryExercise.cpp : 定义 DLL 应用程序的导出函数。

#include "stdafx.h"

_declspec(dllexport) int add(int a, int b)
{
	return a + b;
}

需要注意的是,如果需要导出一个全局函数,就需要在其前用关键字来声明:_declspec(dllexport),这是一个windows的函数,在Linux平台下不可用。最后还需要在项目属性中设置以下三个步骤:

取消“预编译头文件”:配置属性——C/C++——预编译头——创建/使用预编译头——不适用预编译头。 改为/Mtd编译:配置属性——C/C++——代码生成——运行时库——多线程调试(/Mtd)。 修改输出的dll名字:配置属性——链接器——输出文件 ——改为Add.dll。

编译后即可在当前目录下找到Add.dll以及Add.lib文件。下面解释Add.dll和Add.lib的区别:

.dll文件包含所有编译出的二进制指令

.lib文件包含一个列表,表明相对应的.dll文件中有哪些符号,每个符号对应在dll中的位置。

因此dll文件要比lib文件大得多。

2> 在应用程序中使用动态库

在新创建的项目中创建main.cpp,并在其中添加如下代码:

#include <stdio.h>

//使用库
#pragma comment(lib,"Add.lib")

//声明:此函数需从dll导入
_declspec(dllimport) int Add(int a, int b;)

int main(int argc, char** argv)
{
    int result = Add(2, 3);
    printf("Result is %d \n", result);
    return 1;
}

同时将Add.dll和Add.lib放在规定目录下,否则找不到。强调:导入和导出分别使用命令:_declspec(dllimport)和_declspec(dllexport),需加以区分。dll文件需放在以下五个目录中的任意一个即可被操作系统找到:

  1. 可执行文件所在目录;

  2. 进程当前目录;

  3. 系统目录,如C:\Windows\System32等;

  4. Windows目录,如C:\Windows;

  5. 环境变量(系统变量)PATH中的目录。(注:环境变量修改后重启生效!)

2. DLL的加载、卸载与多进程的数据段

需要明确的是,dll文件并不能独立运行,只有当可执行文件.exe加载它时,他才能运行。在exe中有一些标志性信息,表明了此exe文件需要依赖那些dll文件,操作系统即在上述五个目录开始寻找dll文件。exe被加载到内存,形成一个进程(process),dll也被加载到内存;此时进程可以直接调用dll里的函数。因此一个可执行文件实体可以有多个进程,那么我们就来考虑一个问题,当多个进程同时调用一个dll时,dll的全局数据段是共享的吗?考虑一下代码:

//export.cpp
#include <stdio.h>

static int value = 0;

_declspec(dllexport) void ValueSet(int a)
{
    value = a;
}

_declspec(dlliexport) int ValueGet()
{
    return value;
}

//import.cpp

#include<stdio.h>
#pragma comment(lib, "my.lib")

_declspec(dllimport) int ValueGet();
_declspec(dllimport) void ValueGet(int a);

int main()
{
    int a = ValueGet();
    printf("Value : %d", a);

    ValueSet(120);
    int a = ValueGet();
    printf("Value : %d", a);
    printf("&Value : %f", &Value);
    getchar();
    return 1;
}

从上述代码可以看出,value作为dll中的一个静态全局变量,在第一次运行import.exe退出进程前值被置为120,那么问题在于,当地一个进程不退出,再次运行import.exe时,输出的value是0还是120呢?答案是0!这说明一个问题:进程之间调用dll并没有影响。原因在于当dll被加载时,代码段被加载一次,是公共的;而数据段各自程序拷贝一次,是私有的。

注意事项:

  • 当有exe运行时,dll被加载,文件处于被占用状态,不能删除,移动,直到它被卸载。

  • 当所有进程都退出时,dll被卸载。

  • 不同进程之间不能比较dll中的变量的地址,如上import.cpp中每次运行第三个printf输出结果都是相同的。(虽然数据段是私有的,但是地址却是相同的,原因在于采用了虚拟地址)

3. DLL中的动态内存分配

在dll中的malloc的内存,必须在dll中free。(这是由windows决定的)可看以下实例:

//export.cpp
#include <stdio.h>

#define MYDLL _declspec(export)

MYDLL int* MyAlloc(int size)
{
    int* p = malloc(size * sizeof(int));
    
    for(int i = 0; i < size; i++)
    {
        p[i] = i;
    }
    return p;
}

MYDLL void MyFree(int* p)
{
    free(p);
}

//import.cpp
#include <stdio.h>
#include <stdlib.h>

#pragma comment(lib, "my.lib")
#define MyDLL _declspec(import)
MyDLL int* MyAlloc(int size);
MyDLL void MyFree(int* p);

int main(int argc, char** argv)
{
    int* p = MyAlloc(4);
    
    free(p);     //在dll内分配的动态内存在dll外释放会报错
    return 1;
}

 

 正确的做法应该是将free(p)改成MyFree(p).

4.为DLL添加头文件

如果用户利用以上方法对dll中的函数进行声明,不仅给用户带来很多麻烦,而且用户要对dll中有哪些函数非常清楚,这显然是不可能做到的,因此按照惯例,应由模块的作者提供头文件,头文件中应有类型和函数声明。

1>  为DLL创建头文件

//mydll.h
//这个.h文件在编译生成APP的项目和用户实际使用的项目中是通用的,其起作用的方式是条件编译。

#ifndef _MYDLL_H_
#define _MTDLL_H_

#ifdef MYDLL_EXPORT
#define MYDLL _declspec(dllexport)    //在编译dll工程的.cpp文件里,定义宏MYDLL_EXPORT
#else
#define MYDLL _declspec(dllimport)    //在用户工程的.cpp文件里,什么都不用定义就行了
#endif

#include <stdio.h>
MYDLL int Add (int a, int b);

#endif

//mydll.cpp
#define MYDLL_EXPORT                    //预编译规定“输出选项”,用作编译dll工程里的cpp文件
#include <mydll.h>

int Add(int a, int b)
{
    return a + b;
}

生成dll、lib文件后,将dll、lib和h文件一并拷贝至目标工程文件夹,目标工程cpp调用dll文件中函数如下,用户根据头文件即可知道dll中函数的相关信息,同时也省去了导入函数的麻烦。

#include <stdio.h>
#include <mydll.h>                    
//此处不需任何其他宏定义,h文件中MYDLL自动被编译为_declspec(import)

#pragma comment(lib, "mydll.lib")

int main(int argc, char** argv)
{
    int result = Add(10, 11);
    printf("Result : %d", result);
    return 1;
}

2> DLL相关文件的部署

可将dll的相关文件部署到指定文件夹,并将头文件作为系统文件导入。创建mydll文件夹,包含子文件夹include与bin,其中include存放头文件,bin里存放dll与lib文件。这样就可以用尖括号包含了。

#include <mydll.h>        //C++中尖括号表示系统文件,双引号表示用户自己的头文件

3> 用户DLL的配置

与OpenCV的配置相似,在VC++目录中配置包含目录——添加include,库目录——添加bin,同时将dll文件部署到系统能找到的5个目录之一即可(OpenCV的选项是添加到环境变量中)。

5.在DLL中导出一个类

导出类的定义,实际上就是导出类的成员函数,关于h文件等操作与导出普通函数极为相似,只需注重语法上的问题。

//myClassDll.h         在此文件中保存类的定义

#ifndef _MY_CLASS_DLL_H
#define _MY_CLASS_DLL_H

#ifdef MYDLL_EXPORT
#define MYDLL _declspec(dllexport)
#else
#define MYDLL _declspec(dllimport)
#endif

class MYDLL MyObj        //整个类的导出和导入只需此处用到MYDLL
{
public:
    MyObj(int v);
    void display();

private:
    int value;   
}

#endif

//myClassDll.cpp
#include <stdio.h>
#define MYDLL_EXPORT
#include "myClassDll.h"

//在cpp中定义的成员函数无需再使用关键字MYDLL导出
MyObj:: MyObj(int v)
:value(v)
{
}

void MyObj:: diplay()
{
    printf("Value: %d", value);
}


//Target.cpp 目标工程cpp
//包含头文件和lib后直接实用类创建对象
#include <stdio.h>
#include "myClassDll.h"

#pragma comment(lib, "myClassDll.lib")

int main(int argc, char** argv)
{
    MyObj object(123);
    object.display();
    
    return 1;
}

6. 静态库的编译

静态库相比于动态库而言要简单得多,没有动态库的导入和导出操作,其优缺点、适用范围等也与动态库有着很多不同。首先我们看一下静态库的实质:静态库仅有一个.lib文件,其中直接含有代码段和数据段,在连接过程中,相当于直接把代码和数据替换过来,形成完整的可执行程序,因而最终生成的.exe文件是对.lib文件没有依赖的,从体积上看,静态库lib的大小要比动态库的lib大得多。

1> 编写一个静态库文件并调用

// mylib.h 静态库h文件
#ifndef _MYLIB_H_
#define _MYLIB_H_

int Add(int a, int b);

#endif

//mylib.cpp 静态库cpp文件
#include "mylib.h"

int Add(int a, int b)
{
    return a + b;
}

从上述代码段来看,静态库文件的编写和普通h和cpp文件的编写并无差别。在配置属性——连接器——输出中可设定编译后lib文件的名称和位置,注意同dll文件一样,需要在配置属性——C/C++——预处理器中取消预编译头。

2> 调用一个静态库文件

将编译生成的lib文件同h文件一并拷贝至目标工程文件夹下,创建APP.cpp并输入以下代码,完成对库的调用。

//APP.cpp
#include <stdio.h>

#include "mylib.h"
#pragma comment(lib, "mylib")

int main(int argc, char** argv)
{
    int result = Add(10, 11);
    printf("Result : %d", result);
    return 1;
}

3> 静态库的几点说明

  • 对静态库的使用有所限制,某一版本VS编译的静态库文件只能供同一版本VS的工程调用;编译静态库的工程与调用静态库的工程以下属性必须相同:配置属性——C/C++——代码生成——运行时库(要是Mtd都是Mtd等等),否则会出现LINK Warning LNK4098。

  • 静态库的优点:使用静态库生成的exe文件不再依赖于lib文件。

  • DLL的优点: 便于升级更新,只要接口保持不变,可直接替换DLL来升级程序,并不需要重新编译程序。

7. 动态库的手工加载

在上述加载DLL的过程中,exe文件在开始运行时首先加载所有用到的dll文件,再运行,被称为动态库的自动加载。也可以在编译时不指定dll,在运行时调用LoadLibrary来加载动态库,使用FreeLibrary来卸载动态库,这种方式被称为手动加载,它提供了一种在运行时、手工加载dll的技术手段,增加了编程的灵活性。

1> 手工加载示例

对DLL的3要求:

  • 要求待调用函数按照“C”方式编译

  • dll文件可被系统搜索到

//mydll.h 

#ifndef _MYDLL_H_
#define _MYDLL_H_

#include <stdio.h>

#ifdef MYDLL_EXPORT
#define MYDLL _declspec(dllexport)
#else
#define MYDLL _declspec(dllimport)
#endif

extern "C" MYDLL int Add(int a, int b);  //将函数声明为一个C函数

#endif

//mydll.cpp

#include "mydll.h"

int Add(int a, int b)
{
    return a + b;
}

2> 关于extern "C"的说明

首先需要弄明白C函数与C++函数的区别。在存储时,函数和变量一样,都占有一定的内存空间,而函数名被加以修饰后,可作为函数内存空间的首地址,联想类比数组。C++函数的一个重要特性在于函数的可重载性,一般C函数的修饰的是固定的,例如int Add(int a, int b)函数,可能存储时首地址名为_Add,而C++由于重载的特性,存储时更为负载,有可能是将形参都列入函数名,如_Add_int_int等(这里只是举个例子,具体情况是编译器而定)。而extern “C”的作用是让编译器以C函数的方式编译目标函数,从而实现后期能够找到dll函数地址。

3> 手动加载方式

将dll文件放在系统可循的目录下后,在主程序中按如下代码手动加载dll

#include <stdio.h>

//包含windows相关头文件
#include <winsock2.h>
#include <windows.h>

int main(int argc, char** argv)
{

    HINSTANCE handle = LoadLibrary("my.dll");
    if(handle) //如果动态库加载成功
    {
        //定义要找的函数原型,用函数指针的形式
        typedef int (*DLL_FUNCTION_ADD) (int, int);      DLL_FUNCTION_ADD为关键字,括号必须有
        
        //找到目标函数地址
        DLL_FUNCTION_ADD dll_func = (DLL_FUNCTION_ADD)GetProcAddress(handle, "Add");
        if(dll_func)
        {
            //调用该函数
            int result = dll_func(10,20);
            printf("Result : %d", result);
        }
    }
    
    FreeLibrary(handle);
}

说明:

  • 需要配置属性:配置属性——常规——字符集选择使用”使用多字节字符集“ ,如果使用Unicode则会找不到函数LoadLibrary。

  • 不需要h文件和lib文件一样可以使用

  • 即时实用即时卸载

8. VC项目的静态编译

下面来解释一下前面用到的MT/MTd编译和MD/MDd编译,并介绍VC静态编译技术。

一个exe文件在发布后,如果拿到一个新的环境的机子上跑很可能会出错,因为他们的电脑环境很可能缺少必要的VS的dll文件,因此为了解决这一问题,VS给出了静态编译的解决方案。

对于VC而言:

  • ”静态编译”,/MT、/MTd——是指实用libc和msvc相关的静态库进行编译

  • “动态编译”,/MD、/MDd——是指实用相应的DLL版本编译。

我们在配置属性——C/C++——运行时库即可做相应改变。

 

相关英文解释:d——debug、M——Multi-threading(多线程)、T——Text、D——Dynamic

 

作者冷风哈,QQ:164989932

码字不易,转载请注明出处。

C++的LoadLibrary动态加载dll 1、导出接口 //抽象类 class CSDExMotionDev { virtual bool Ex_OPenDev(const SPLCMotionDev1D sysDev)=0; virtual bool Ex_OPenDev()=0; //.. } //输出接口 extern "C" __declspec(dllexport) HRESULT CreateMoti... 阅读详情

相关推荐

Cherno C++ P50 C++中使用动态库

Cherno C++学习笔记

weixin_44452626的博客 628

C++ 操作DLL的函数 Loadlibrary GetProcAddress FreeLibrary

LoadLibrary("文件名"):返回得到的模块句柄,可以加载一个动态连接库或exe文件。 例: HINSTANCE hLib = NULL; string path = g_strExeFilePath + "\\xx.dll"; LPCSTR strPath = path.c_str(); hLib = LoadLibrary(strPath); if (hLib == NULL) { printf("LoadLibraryA()失败! ...

AI浩 7976

Python脚本自动化芯片设计?PyAether实战教程带你玩转EDA

本文通过PyAether实战教程,详细介绍了如何利用Python脚本实现芯片设计自动化。内容涵盖环境搭建、核心对象模型解析,并重点演示了原理图自动生成、参数化单元创建及设计验证流程集成,帮助EDA工程师从重复性手动操作中解放,显著提升设计效率与一致性。

e4f5g6h的博客 1314

【c/c++】静态库

1、静态库介绍 静态库是指在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”文件;在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中的这种库。 程序编译一般需经预处理、编译、汇编和链接几个步骤。静态库特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。 静态库和动态库是两种共享程序代码的方式,它们的区别是:静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动

StudyWinter的博客 6686

PHP版本对接支付宝支付接口 电脑网站 详细介绍 沙箱环境 超简单易懂

PHP版本对接支付宝支付接口 其实理顺了思路后,按照我接下来的步骤来,真的超级简单啊,为啥有那么多的朋友们折腾了那么久呢,嘿嘿,跟我走吧~ 我是昨天晚上洗完澡之后,大概八九点,才开始正式开工尝试去这一工程的,我去支付宝的蚂蚁金服开放平台里把各个知识点和文档大概都看了一遍,大致弄明白了要怎么操作了,建议大家看看电脑网站开发文档,忙到了夜里十二点左右,成功地用支付宝给的Demo完成了付款操...

爱玲姐姐的博客 1万+

vivado2020.1使用vitis生成QSPI启动文件报错

在使用vivado2020.1使用vitis,生成QSPI启动文件时会报错,data2mem命令无法识别,这是因为data2mem是xilinx7series芯片的命令,当使用ultrascale/ultrascale+芯片时则需要使用updatemem命令,这或许是vitis的一个bug吧,明明选择的是ultrascale的芯片,却一直调用打她mem命令,挺麻烦的,需要手动执行,在XSCT console窗口执行的命令如下: updatemem -force -meminfo \ F:/xc7z35t/x

qq_32134427的博客 2336

C++_LoadLibrary ()函数

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33726313的博客 9818

Xilinx SDK工程编译、链接、调试注意事项

1、添加工程 启动SDK时选取workspace,如下图所示: 对应的workpace文件夹中会生成如下几个文件: 如果当前workspace是首次加载工程,SDK会进入启动界面 点击Import Project,导入已有工程 点击Browse,添加工程路径,一个完整的工程包含一个bsp文件夹,一个HW文件夹,和一个src文件夹(添加C功能函数) 点击Fini...

Autumn_He的博客 1万+

C/C++动态库与静态库学习笔记

动态链接和静态链接是程序构建时处理库代码的两种不同方式。静态链接在编译阶段将库代码直接打包到最终的可执行文件中,生成的文件独立性强,但体积较大,且库更新时需要重新编译整个程序;而动态链接则是在程序运行时才加载所需的共享库(如Linux的.so或Windows的.dll文件),这种方式显著减小了可执行文件的体积,多个程序可以共享同一份库代码,节省内存,同时库的更新只需替换共享库文件即可生效,无需重新编译主程序。不过动态链接的运行时依赖需要确保库版本兼容,且启动时会有少量解析开销。静态链接适合嵌入式或需独立分发

小L的博客 1064

算法策略 | MACD跨周期短线交易策略开发(股指+商品双版)

量化策略开发,高质量社群,交易思路分享等相关内容

松鼠宽客的博客 2538

数学建模学习(5):最全概率分析之图表绘制详解,内容比较多,建议收藏

(1) 绘制正整数频率使用 tabulate(X) (2)

全栈川川 4591

C++学习笔记:静态库和动态库

在大型工程中会经常使用到库文件,一个原因是软件的不同功能通常由不同的开发人员负责,如果都使用源文件,维护和测试将是个十分头疼的问题。此外,开发者有时并不想将代码开源,库文件也可以将源代码隐藏起来。在Windows和Linux下,库文件的本质和基本使用方式是相同的。本文针对静态库和动态库的生成和使用方法展开详解。

dingxiaoxv的博客 816

ClaudeCode入门01-环境安装(小白入门:手把手教你配置,超简单的一种接入方式)

文手把手教你从零搭建 Claude Code 开发环境。针对国内网络现状,我们采用 OpenRouter + Claude Code Router 的方案,支持支付宝/微信充值,无需科学上网即可完成配置。内容涵盖 Node.js 安装(macOS/Windows/Linux)、OpenRouter 注册与充值、Claude Code 和 Router 安装配置,以及一键启动脚本的编写。跟着截图一步步操作,10分钟搞定全部环境!

yueyeguzhuo的专栏 279

C++学习笔记(二十八):c++ 静态库及动态库的使用

库的使用会很大程度减少我们的工作,本节对c++中静态库和动态库的使用进行简单的介绍。 静态链接库意味着这个库会被放到可执行文件中,在生成的exe中。动态链接库是在程序运行时链接的,可以在程序运行时调用加载库函数的方法来实现,Windows中通过loadLibrary函数完成,也可以在程序启动时通过加载dll文件来动态链接库。主要区别是库文件是否被编译到可执行文件中。 一般网上下载的库都包含库文件和include文件,对于visiualstudio项目,我们必须把include文件指向头文件,这样我们就可

qq_16701727的博客 676

【汽车 OTA 】差分升级

汽车 OTA 差分升级,本质是在整包 OTA 的基础上,通过“只传变化”的方式,大幅减少下载数据量、时间和成本,是当前车端软件升级的主流方向之一。

天赐好车的博客 482

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

gnu make 手册 学习笔记 C语言 / C++ 构建工具 part.6 编译 静态库 动态库

6.静态库,动态库 库命名规范 gcc下: 静态库 libxxxx.a 动态库 libxxxx.so 或者加上版本号 libxxxx.so.major.minor window下: 静态库 xxx.lib 动态库 xxx.dll 6-1.静态库 最简单的理解方式是,将.c的源文件,编译为.o文件,然后使用ar命令,将同一个lib的.o文件打包在一起。 6-1-...

lijinken的博客 356

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

嵌入式Linux2月11日学习笔记

在编译多个c文件时,可以单独把各个的c文件编译成机器文件(gcc -c -o main.o main.c),最后在统一链接为APP(gcc -o test main.o sub.o),这样在后续修改时,不用每一个文件都在编译一次,提高效率。编译就是把 C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码,所用到的工具为 cc1(它的名字就是 cc1,x86 有自己的 cc1 命令,ARM 板也有自己的cc1 命令)。与静态库不同,动态库不会被直接嵌入到可执行文件中,而是以共享的方式加载。

m0_72142123的博客 1452

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Wily的CPP学习笔记

通常情况下,要实现成员函数作为回调函数:一种过去常用的方法就是把该成员函数设计为静态成员函数(因为类的成员函数需要隐含的this指针 而回调函数没有办法提供),但这样做有一个缺点,就是会破坏类的结构性,因为静态成员函数只能访问该类的静态成员变量和静态成员函数,不能访问非静态的,要解决这个问题,可以`把对象实例的指针或引用做为参数传给它`。第二种:包含源文件的子文件夹**未包含**CMakeList.txt文件,子目录的编译规则要体现在主目录的CMakeList.txt中。list+函数名字:查看具体函数)

qq_36545593的博客 367

C++静态库与动态库的区别

                &nbs...

Quantai的博客 4660

C++静态库与动态库

打开工程“属性面板”è”配置属性”è “C/C++”è” 常规”,在“附加包含目录”属性值中,键入DynamicMath.h 头文件所在目录的路径或浏览至该目录。打开工程“属性面板”è”配置属性”è “C/C++”è” 常规”,在“附加包含目录”属性值中,键入StaticMath.h。打开工程“属性面板”è”配置属性”è”常规”,配置类型选择静态库。l -l:指定链接时需要的动态库,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a或.so来确定库的名称。

A19720252059的博客 1673

【Linux】动态库与静态库

本篇文章博主会与大家共同学习动静态库的相关内容,涉及到动静态库的基本知识与特征,动静态库的打包与使用等内容。

℉f的博客 2474

C++ 静态库与动态库详解

静态库是“编译时打包”,适合追求独立运行、小体积库的场景,但更新成本高;动态库是“运行时共享”,适合需频繁更新、多程序复用的场景,但依赖管理复杂。实际开发中,需根据项目规模、更新频率、部署需求选择:小型工具或嵌入式场景常用静态库;大型应用(如 GUI 程序、系统工具)多用电动态库。在 C++03 环境下,需重点关注平台差异(编译器命令、文件格式)和名称修饰问题,确保库的兼容性。

bkspiderx的博客 1530

C++静态库和动态库的导入导出

C++静态库的导出导入。 C++动态库函数的导出导入。 C++动态库类的导出导入

weixin_38800448的博客 1万+

【Linux:动态库与静态库】

有关Linux动静态库的详细讲解,帮助你更加深刻的认识和理解动静态库。

m0_68872612的博客 2126

C++ 动态库与静态库的区别:从原理到应用

静态库在编译时完整嵌入可执行文件,生成独立、无外部依赖的程序。优点是部署简单、无版本兼容问题;缺点是每个程序都包含一份库代码副本,磁盘和内存占用大,库更新需要重新编译所有使用它的程序。动态库在运行时由操作系统动态加载,多个进程可共享同一份物理内存中的库代码。优点是节省磁盘和内存空间,支持热更新(替换库文件即升级),适合实现插件机制;缺点是部署时需要确保目标系统存在正确版本的库文件(DLL Hell 问题),加载时有额外的符号解析开销。选择原则需要多程序共享、节省内存→ 动态库需要热更新或插件机制。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 986
上一篇: 亡羊补牢——error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项的原因及解决方案
下一篇: 亡羊补牢——出现系统丢失MSVCR120d.dll、MSVCP120d.dll丢失的问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值