首页 > 系统相关 >MinGW、Linux GNU、MSVC编译和链接动态库的分析

MinGW、Linux GNU、MSVC编译和链接动态库的分析

时间:2023-02-09 16:58:03浏览次数:42  
标签:GNU 导出 dll 编译 MinGW Linux 动态 链接

这几天研究CMake跨平台项目嘛,用了以下几种编译器:

  1. VS2019(MSVC)

  2. Linux GNU

  3. MinGW

编译之后发现链接动态库发现以下问题:

  1. VS2019中如果直接链接CMakeLists.txt中生成的动态库,编译的时候会发生unreferenced的错误,相同的CMake项目使用MinGW或者Linux GNU进行编译的话则没有问题。

对于这个问题,我回想起了在上一家公司实习的时候,写VS项目的dll要配置导出接口的事情,当时之所以觉得导出接口陌生是因为我在实习前基本上都是用MinGW,所以编译产生的动态库不需要导出接口就可以直接用,当时没有细究这个问题,以为在windows下都是一样的,然后现在就遇到了这个问题。

通过对不同平台以及不同编译器进行测试,我得到了以下结论:

  1. 结论一:MinGW和Linux GNU都是GNU,所以它们编译产生的文件有相似的地方:静态库的后缀名都是.a,但是区别也有,Linux GNU编译动态库产生so,MinGW编译动态库会产生dll(如果使用MSYS2的话确实是编译出so),不过这不重要;
  2. 结论二:MinGW编译动态库除了产生dll外还会产生一个dll.a;
  3. 结论三:VS项目的函数如果使用函数导出接口修饰的话,编译动态库也会产生一个与dll同名的lib。

然后编写lua的C包的时候也发现了:

lua在require或者loadlib一个C模块的时候,如果模块是用VS编译产生的话,函数必须具有导出接口,而如果模块是用MinGW编译产生的话,则不需要,也就是说MinGW编译生成动态库时,动态库中的函数默认具有导出接口,这部分我应该开一篇新文,在这里只是题外话。

然后再进行测试,我发现MinGW编译动态库产生的dll可以直接进行动态库链接,结论2中产生的dll.a这个引导库也许是为了和在Windows下使用动态库一致,但是由于MinGW生成动态库时一定会生成dll.a所以我没办法判断MinGW链接动态库的时候是链接dll还是链接dll.a,反正在lua的例子中可以知道MinGW生成的动态库中所有函数都是具有导出接口的;而VS编译动态库产生的dll必须需要有一个引导库文件来帮助完成链接工作。

在cmake中进行动态库链接的话:

target_link_libraries(main testlib_shared) 
#这一行代码在MinGW、Linux GNU上cmake产生的makefile是可以通过编译的,而如果testlib_shared中用到的函数有使用函数导出接口修饰的话,cmake产生的VS项目也可以通过编译

当然最后得有一个结论:为了让cmake项目能够跨平台,链接的动态库中使用到的函数应该使用函数导出接口修饰或者直接链接静态库,这样项目才能够在VS上通过编译,而代码中添加函数导出接口修饰的话需要用宏_WIN32去判断是不是VS项目:

#ifndef _WIN32 //如果没有_WIN32的宏,说明不是MSVC项目,自然就不用导出接口
#define TEST_DLL_API
#endif

#ifndef TEST_DLL_API
	#define TEST_DLL_API __declspec(dllexport)
#endif

#include <stdio.h>

TEST_DLL_API int hello();

标签:GNU,导出,dll,编译,MinGW,Linux,动态,链接
From: https://www.cnblogs.com/thankvincisdaily/p/17106131.html

相关文章

  • Linux基础部署项目
    一、安装jdk:1.jdk安装包一般放在/usr/local中cd/usr/localmkdirjava将安装包放java目录中2.linux中自带一个Openjdk,但是我们不需要他,需要吧他卸载查看java环境:jav......
  • Linux基础课:第八章笔记--租云服务器及配环境
    最后一节课--完结撒花理解框架关系docker教程sudousermod-aGdocker$USER赋予用户sudo权限,加入到用户组中scp/var/lib/acwing/docker/images/docker_lesson_1_......
  • linux 中如何给普通用户增加管理员权限
     001、使用root用户编辑配置文件:vim/etc/sudoers在root  ALL=(ALL)    ALL行下面增加如下内容(其中liujiaxin02是普通用户名):liujiaxin02   ALL=(ALL)......
  • Linux系列教程(六)——Linux常用命令之文件搜索命令
    前一篇博客我们讲解了​​Linux链接命令和权限管理命令​​, 通过ln-s 链接名表示创建软链接,不加-s表示创建硬链接;还有三个更改权限的命令,chmod命令可以更改文件或......
  • UBUNTU 22.04关闭selinux
    一、打开文件vim/etc/selinux/config二、更改为如下SELINUX=disabled三、从启动服务器reboot......
  • linux常用命令
    man帮助手册--help帮助手册date日期cal日历pwd显示当前所在目录cd切换目录Ls-lll显示当前目录下的内容grep通过|管道符,配置grep进行......
  • Linux文件与目录结构
    linux一切皆文件linux系统的目录结构/bin(/usr/bin、/usr/local/bin)是Binary的缩写,这个目录存放着最经常使用的命令/sbin(/usr/sbin、/usr/local/sb......
  • 进阶技术:Linux Arm32是如何调用C Main的
    前言:Linuxx64通过qemu的rdinit方式调用的CMain,实际上是通过load_elf_binary(加载和解析elf)和start_thread(设置Ip和sp),用缺页异常来调用。那么Arm32里面是如何调用CMa......
  • linux centos中利用命令行发送邮件
     001、date|mail-s"Subject"[email protected]##发送一个日期    002、date|mail-aa.ped-s"Subject"[email protected]......
  • Linux 系统管理 07——文件系统与 LVM
    一、创建文件系统mkfs、mkswap命令1、mkfs命令(1)作用:创建文件系统(格式化)MakeFilesystem(2)格式:mkfs  –t  文件系统类型  分区设备      (mkfs.文......