Qt使用MinGw和MSVC两种方法生成静态库和动态库

静态库与动态库

静态库

特点


1. 文件扩展名
   - 在 Windows 上:.lib(msvc),.a(mingw)
   - 在 Unix/Linux 上:`.a`

2. 链接方式
   - 在编译时将库的代码直接嵌入到可执行文件中。

3. 代码重用
   - 多个可执行文件共享相同的库代码,但是每个可执行文件都有库代码的副本。

4. 运行时独立性
   - 静态链接的可执行文件在运行时不依赖库文件,所有代码都包含在可执行文件中。

优点


1. 独立性
   - 一旦生成可执行文件,它不再依赖于外部库文件,便于分发和部署。
2. 性能
   - 由于所有代码在编译时已经确定,加载速度更快,运行时没有动态链接的开销。

3. 兼容性
   - 避免了不同版本库之间的兼容性问题,确保了运行时的稳定性。


缺点

1. 文件大小
   - 每个静态链接的可执行文件都包含库的副本,增加了文件大小。

2. 更新困难
   - 如果库有更新,需要重新编译所有依赖该库的可执行文件。

动态库

 特点

1. 文件扩展名
   - 在 Windows 上:`.dll`
   - 在 Unix/Linux 上:`.so`

2. 链接方式
   - 在运行时将库文件动态加载到可执行文件的地址空间中。

3. 代码重用
   - 多个可执行文件共享相同的库文件,节省内存和磁盘空间。

4. 运行时依赖性
   - 可执行文件在运行时依赖于外部库文件。

优点 

1. 节省资源
   - 共享库文件,多个程序可以共享相同的库,节省磁盘空间和内存。

2. 易于更新
   - 库文件更新后,所有依赖该库的程序无需重新编译,只需确保新版本库的兼容性。

3. 模块化
   - 可以将应用程序分解为多个模块,易于管理和维护。

  缺点

1. 依赖性
   - 可执行文件在运行时依赖于外部库文件,如果库文件缺失或版本不兼容,程序将无法运行。

2. 加载时间
   - 由于在运行时需要动态加载库文件,启动速度可能稍慢。

3. 版本控制
   - 不同程序可能需要不同版本的库,容易引起“DLL地狱”问题,即版本冲突。

生成

动态链接(Dynamic Linking)是一种链接方式,在这种方式下,库文件在程序运行时而不是在编译时被加载。这些库文件被称为动态库共享库(在 Windows 上称为 DLL,Dynamic Link Library;在 Unix/Linux 上称为 .so,Shared Object)。

静态链接(Static Linking)是在编译时将库文件的代码复制到每一个使用该库的可执行文件中。这种方式生成的库文件被称为静态库(在 Unix/Linux 上通常以 .a 结尾,在 Windows 上通常以 .lib 结尾)。

总结

选择使用静态库还是动态库,取决于具体的应用场景和需求,两者都有其优点和缺点

静态库:适用于需要独立部署、更新频率低、对启动速度和兼容性要求高的场景。
动态库:适用于模块化设计、需要节省资源、库文件更新频繁的场景。

延申

lib库实际上分为两种,一种是静态链接lib库或者叫做静态lib库(就是我们常说的静态库),另一种叫做动态链接库dll库的lib导入库或称为lib导入库。这两个库是不一样的,很多人都分不清楚,很容易混淆。下面我给你解释清楚,你就不会再糊涂了。
第一种是静态lib,包含了所有的代码实现的,是源代码文件.c或.cpp文件编译生成的,这个lib库就是文本形式的源代码编译后的二进制形式代码。

所以只要导入后,使用链接器链接生成exe文件后,那么exe文件就可以直接使用exe 内部的代码了。这个链接lib库的过程就相当于把lib库里的所有二进制的代码复制到exe文件中。所以,链接完后,静态lib库文件就不需要了。最后, 我们只要exe就行了。但是,每次编译链接生成exe时都需要这个静态lib库哦。这意思是说,最后你给别人的只需要给一个exe就行了,就不必将lib也给别人。在写代码时,我们要调用lib库里的函数,我们是通过提供的头文件来知道lib静态库里都有些什么函数的。

第二种就是lib导入库,这个库只是dll文件中的所有函数在dll文件中的地址的说明。

这个lib导入库可以说明dll的内部结构,简直就对dll内部了如指掌,我们通过lib导入库,就可以轻松调用到dll里面的函数。而我们在程序中使用 dll的时候,我们导入lib导入库之后,然后将dll放入项目中,就可以直接使用,就好像dll里的代码就和我们写的cpp源代码文件一样。所以非常方便,这也是lib导入库存在的理由了。而dll的使用,还可以直接使用API函数来获取dll内部的函数的地址,然后将函数类型转换为正确的函数类型。而这些函数类型声明就在提供的头文件中了。头文件和我们自己写的头文件一样的。这个过程呢,就非常麻烦了,这才有上面那个lib导入库的存在的空间了。同样,lib导入库在编译链接后,那么dll里的函数地址结构等信息也都复制到exe里面了。所以,最后生成程序之后,lib导入库和静态lib一样的命运,那就是被抛弃了。哎,现实已经很残酷了,在计算机里,更是残酷。

MinGW 编译与MSVC编译

在项目文件(.pro)中,可以通过指定CONFIG变量来指定是生成动态库还是静态库。

MinGW 编译

1. 动态链接
   在Qt中默认生成的就是动态库

2. 静态链接
    - 要静态链接库文件,可以在pro文件中添加CONFIG += staticlib

MSVC 编译

1. 动态链接
   在Qt中默认生成的就是动态库

2. 静态链接
    - 要静态链接库文件,可以在pro文件中添加CONFIG += staticlib

不同点

1. 工具链
    - MinGW 使用 GNU 工具链,MSVC 使用微软的 Visual Studio 工具链。

2. 库文件
    - MinGW 通常使用 .a 文件,MSVC 使用 .lib 文件。

3. 性能和二进制兼容性
    - MSVC 编译的程序在 Windows 上可能有更好的优化和兼容性,特别是在与其他 MSVC 编译的库交互时。

4. IDE 支持
    - MinGW 通常与 Qt Creator 一起使用,而 MSVC 常与 Visual Studio 一起使用,但也可以在 Qt Creator 中配置使用。

MinGW 下编译动态库与静态库

动态库

第一步:打开Qt Creater,新建库项目

自己起个库名,最好有大小写,要不然后面可能报错

第二步:选择库类型,选择依赖

第三步:选择mingw

完成后可以看下pro文件内容

第四步:为库添加内容

FirstDll.h

#ifndef FIRSTDLL_H
#define FIRSTDLL_H

#include "FirstDll_global.h"

// DllMain() 是动态链接库(DLL)的入口点函数,类似于构造函数。
// DllMain 主要处理 DLL 模块的初始化和清理工作,响应系统对 DLL 的加载、卸载等事件。
// DllMain 通常不在 .h 文件中声明,而是在 .cpp 文件中定义。

class FIRSTDLL_EXPORT FirstDll
{
public:
    FirstDll();
    int add(int a, int b);
    void print();
    bool isFalse;
};
// 在动态库中定义的函数和变量可以定义在类外部,也可以定义在类内部。
// 这里的 extern "C" 用于防止 C++ 编译器对函数名进行“名字修饰”(name mangling),
// 使得函数可以被 C 语言或其他不支持 C++ 名字修饰的语言调用。
/*************************************************************
extern "C"
在C++中,函数名在编译时会被“名字修饰”(name mangling),
这是为了支持函数重载等C++特性。然而,
这种名字修饰会使得C++编译的函数名与C编译器产生的函数名不同,
从而导致链接错误。当你希望C++库能够被C程序(或其他不支持C++名字修饰的语言)调用时,
你需要使用 extern "C" 来告诉编译器以C语言的方式处理这些函数,不进行名字修饰。

MYDLL_EXPORT
MYDLL_EXPORT 是一个宏,它根据当前是构建库(定义 MYDLL_LIBRARY)还是使用库(未定义 MYDLL_LIBRARY)
来解析为 Q_DECL_EXPORT 或 Q_DECL_IMPORT。这允许库在构建时导出符号,而在其他程序中使用库时导入这些符号。
 ***********************************************************/
extern "C" FIRSTDLL_EXPORT int sub(int a, int b);

#endif // FIRSTDLL_H

FirstDll.cpp

#include "firstdll.h"
#include <iostream>

FirstDll::FirstDll()
{
    isFalse = false;
}

int FirstDll::add(int a, int b)
{
    return a + b;
}

void FirstDll::print()
{
    if (isFalse) {
        std::cout<<"result:"<<isFalse<<"\n"
        isFalse = !isFalse;
    } else {
        std::cout<<"result:"<<isFalse<<"\n"
        isFalse = !isFalse;
    }
}

int sub(int a, int b)
{
    return a - b;
}
第五步:选择release,编译项目

第六步:右键任意文件,在explorer中显示

点击release文件夹

ok

静态库

第一步:打开Qt Creater,新建库项目

第二步:选择库类型,选择依赖

因为就做一个简单的例子,就不依赖Qt的模块了

第三步:选择mingw

完成后可以看下pro文件内容

第四步:为库添加内容

FirstLib.h

#ifndef FIRSTLIB_H
#define FIRSTLIB_H

class FirstLib
{
public:
    FirstLib();
    int add(int a, int b);
    void print();
private:
    bool isFalse;
};

#endif // FIRSTLIB_H

FirstLib.cpp

#include "firstlib.h"
#include <iostream>

FirstLib::FirstLib()
{
    isFalse = false;
}

int FirstLib::add(int a, int b)
{
    return a + b;
}

void FirstLib::print()
{
    if (isFalse) {
        std::cout<<"result:"<<isFalse<<"\n";
        isFalse = !isFalse;
    } else {
        std::cout<<"result:"<<isFalse<<"\n"
        isFalse = !isFalse;
    }
}
第五步:选择release,编译项目

第六步:右键任意文件,在explorer中显示

点击release文件夹

完成

MSVC下 编译动态库与静态库

动态库

第一步:打开Qt Creater,新建库项目

第二步:选择库类型,选择依赖

这里选则动态库,因为仅作测试使用,就不选择依赖了

第三步:选择msvc

完成后可以查看下pro文件内容

第四步:为库添加内容

SecondDll.h

#ifndef SECONDDLL_H
#define SECONDDLL_H

#include "SecondDll_global.h"

class SECONDDLL_EXPORT SecondDll
{
public:
    SecondDll();
    int add(int a, int b);
    void print();
    bool isFalse;
};
// 在动态库中定义的函数和变量可以定义在类外部,也可以定义在类内部。
// 这里的 extern "C" 用于防止 C++ 编译器对函数名进行“名字修饰”(name mangling),
// 使得函数可以被 C 语言或其他不支持 C++ 名字修饰的语言调用。
/*************************************************************
extern "C"
在C++中,函数名在编译时会被“名字修饰”(name mangling),
这是为了支持函数重载等C++特性。然而,
这种名字修饰会使得C++编译的函数名与C编译器产生的函数名不同,
从而导致链接错误。当你希望C++库能够被C程序(或其他不支持C++名字修饰的语言)调用时,
你需要使用 extern "C" 来告诉编译器以C语言的方式处理这些函数,不进行名字修饰。

MYDLL_EXPORT
MYDLL_EXPORT 是一个宏,它根据当前是构建库(定义 MYDLL_LIBRARY)还是使用库(未定义 MYDLL_LIBRARY)
来解析为 Q_DECL_EXPORT 或 Q_DECL_IMPORT。这允许库在构建时导出符号,而在其他程序中使用库时导入这些符号。
 ***********************************************************/
extern "C" SECONDDLL_EXPORT int sub(int a, int b);

#endif // SECONDDLL_H

SecondDll.cpp

#include "seconddll.h"
#include <iostream>

SecondDll::SecondDll()
{
    isFalse = false;
}

int SecondDll::add(int a, int b)
{
    return a + b;
}

void SecondDll::print()
{
    if (isFalse) {
        std::cout<<"result:"<<isFalse<<"\n";
        isFalse = !isFalse;
    } else {
        std::cout<<"result:"<<isFalse<<"\n";
        isFalse = !isFalse;
    }
}

int sub(int a, int b)
{
    return a - b;
}
第五步:选择release,编译项目

第六步:右键任意文件,在explorer中显示

点击release文件夹

完成

静态库

第一步:打开Qt Creater,新建库项目

第二步:选择库类型,选择依赖

第三步:选择msvc

pro文件内容

第四步:为库添加内容

SecondLib.h

#ifndef SECONDLIB_H
#define SECONDLIB_H

class SecondLib
{
public:
    SecondLib();
    int add(int a, int b);
    void print();
private:
    bool isFalse;
};

#endif // SECONDLIB_H

SecongLib.cpp

#include "secondlib.h"
#include <iostream>

SecondLib::SecondLib()
{
    isFalse = false;
}

int SecondLib::add(int a, int b)
{
    return a + b;
}

void SecondLib::print()
{
    if (isFalse) {
        std::cout<<"result:"<<isFalse<<"\n";
        isFalse = !isFalse;
    } else {
        std::cout<<"result:"<<isFalse<<"\n";
        isFalse = !isFalse;
    }
}
第五步:选择release,编译项目

第六步:右键任意文件,在explorer中显示

点击release文件夹

完成

使用

库文件的使用参照我另一篇博客:Qt中外部库的使用(MinGw与MSVC)

参考

lib库知识全面讲解(.lib、.dll)_.lib .dll-CSDN博客

引用\[1\]提到了在切换QT5 MinGWMSVC编译时遇到的问题,引用\[2\]提到了编码的问题,以及QT5的Qstring默认是UTF8格式,而MSVC只支持带BOM的UTF8格式。引用\[3\]提到了MSVC是微软自己的编译器,可以直接运行不需要编译。根据这些信息,可以得出qt mingwmsvc的区别如下: 1. 编译器:QT MinGW使用MinGW编译器,而MSVC使用微软自己的编译器(Microsoft Visual C++ Compiler)。 2. 编码支持:QT MinGW默认使用UTF8编码,而MSVC只支持带BOM的UTF8编码。因此,在使用MSVC编译时,需要注意编码的转换。 3. 依赖库:在使用MSVC编译时,可以直接使用Windows下的OpenCV库,而不需要进行编译。这是因为MSVC的编译器与Visual Studio的版本有对应关系,可以直接运行。 总结起来,QT MinGWMSVC的区别主要在于编译器和编码支持方面。选择使用哪种编译器取决于项目的需求和开发环境的配置。 #### 引用[.reference_title] - *1* [QT5 MinGW切换MSVC编译问题](https://blog.csdn.net/xinlongabc/article/details/121708435)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Qt编译器MinGWMSVC的区别](https://blog.csdn.net/qq_43445867/article/details/127889570)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Windows下的Qt编译器——MinGWMSVC的区别](https://blog.csdn.net/flowerspring/article/details/116924437)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值