VS 2019配置多线程pthread库 - 及自我解析

VS 2019配置多线程pthread库

下载库文件

在学习c++过程中,c++多线程一般需要用到pthread多线程库,这是一般是假设我们使用的是 Linux 操作系统,编译工具是gcc的情况下,但是大多数情况咱们开发的操作系统是Windows,编译工具是Visual Studio。本文章的基础环境是win10,VS 2019。

先去下载pthread库

链接: ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-9-1-release.zip.

解压后会看到有三个文件夹

VS 2019配置多线程pthread库 - 及自我解析_第1张图片
VS 2019配置

我们的测试程序来自菜鸟教程的C++多线程教程
,创好项目后引入pthread的头文件会报找不到的错误。
VS 2019配置多线程pthread库 - 及自我解析_第2张图片
去项目NuGet程序包里下载这个库
VS 2019配置多线程pthread库 - 及自我解析_第3张图片
到浏览中搜索安装

VS 2019配置多线程pthread库 - 及自我解析_第4张图片
安装完后运行程序会遇到第一个错误 C2011 “timespec”:“struct”类型重定义
VS 2019配置多线程pthread库 - 及自我解析_第5张图片
注意:之所以有这个报错,是因为time.h中也有重名声明。

解决方法1,到pthread.h头文件里,在

#if !defined( PTHREAD_H )
#define PTHREAD_H
#define HAVE_STRUCT_TIMESPEC      // 注意,加上HAVE_STRUCT_TIMESPEC

解决方法2,也可以在项目的属性页进行设置,将HAVE_STRUCT_TIMESPEC加在预处理器定义中,效果一样。
VS 2019配置多线程pthread库 - 及自我解析_第6张图片
再次运行,此时会出现两个新的错误
VS 2019配置多线程pthread库 - 及自我解析_第7张图片

疑问1:
我与作者采用相同的环境,但是我没有出现这两个报错。事实上,我NuGet程序包里下载这个库后,就没有报错了。

解决上面无法解析标识的办法是,回到pthread.h头文件里,任意位置上加上

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

注意:经过的的测试,实际上是只用在实际用到 多线程语句(比如:pthread_create())之前加上这句就可以了。

感觉离希望越来越近了,错误说无法打开“pthreadVC2.lib”,咱们把上面下载好的Pre-built.2/lib/x86(选x86还是x64文件夹视你的编译器平台而定)里的找到pthreadVC2.lib

VS 2019配置多线程pthread库 - 及自我解析_第8张图片
把pthreadVC2.lib放到程序根目录下,就是和你的代码放到同一级目录上
VS 2019配置多线程pthread库 - 及自我解析_第9张图片
注意:拷贝文件的路径问题!!

再运行程序,这次终于弹出黑框框了,但是会提醒我们系统里缺少pthreadVC2.dll
VS 2019配置多线程pthread库 - 及自我解析_第10张图片
注意:这个提示是在程序运行时出现的,所以pthreadVC2.dll也必须放对位置。

这时需要将dll库放入Windows系统库文件中

打开Pre-built.2下dll文件夹,有两个不同平台的dll,把x64下的文件放到C:\Windows\System32\下
把x86文件夹放到SysWOW64\下
据说之所以把x64的放32位下,x86的放64位下,是为了让64位机能运行32位的程序

最后一次运行程序,成功运行!
VS 2019配置多线程pthread库 - 及自我解析_第11张图片
疑问2: 已解决

我遇到的问题总结

操作描述:
自己写了一个静态库,静态库中使用了多线程;静态库并没有按照上述操作进行设置,只做了 VS-项目-NuGet程序包里下载pthreads库。解决了错误 C2011 “timespec”:“struct”类型重定义的问题后,静态库编译没有任何问题。

但是,测试程序调用静态库时(链接LIB中使用多线程的函数),出现报错 :错误 LNK2019 无法解析的外部符号 __imp__pthread_create…

为解决问题,先是在测试程序的项目-NuGet程序包里下载pthreads库,编译问题没有解决。
根据本文内容,添加了#pragma comment(lib,“pthreadVC2.lib”),编译问题解决了。并将pthreadVC2.lib文件拷贝到了静态库的目录下和测试程序的目录下。

为了搞明白问题的关键,我做了测试1

列出改变因素:

  • 测试程序没有加载pthreads库;
  • 测试程序根目录下有 pthreadVC2.lib文件;
  • 静态库加载pthreads库;
  • 静态库根目录下有pthreadVC2.lib文件;
  • 静态库中 只有在用到多线程的cpp文件开头增加了如下语句
 // 多线程
#include 
#pragma comment(lib,"pthreadVC2.lib")

测试1结果:再次编译测试程序,编译OK。

还是不清楚,我做了测试2

列出改变因素:

  • 测试程序没有加载pthreads库;
  • 测试程序根目录下有 pthreadVC2.lib文件;
  • 静态库加载pthreads库;
  • 删除 静态库根目录下有pthreadVC2.lib文件;
  • 静态库中 只有在用到多线程的cpp文件开头增加了如下语句
 // 多线程   注意 这两句是加在静态库的一个cpp中的。
#include 
#pragma comment(lib,"pthreadVC2.lib")

测试2结果:单独编译两个项目,都OK。

从结果上看,pthreadVC2.lib文件对静态库是没有作用的。那#pragma comment(lib,“pthreadVC2.lib”)语句起到什么作用呢?

继续测试3

列出改变因素:

  • 测试程序没有加载pthreads库;
  • 删除 测试程序根目录下有 pthreadVC2.lib文件;
  • 静态库加载pthreads库;
  • 删除 静态库根目录下有pthreadVC2.lib文件;
  • 静态库中 只有在用到多线程的cpp文件开头增加了如下语句
 // 多线程   注意 这两句是加在静态库的一个cpp中的。
#include 
#pragma comment(lib,"pthreadVC2.lib")

测试3结果:单独编译静态库OK,编译测试程序,就会报出找不到pthreadVC2.lib,而且错误指向的是静态库的那个cpp文件。

这就有点意思了

我的推测: (可能有误)

项目A用到了pthread,通过项目-NuGet程序包里下载pthreads库,如果只单独使用项目A,那么只需要#include 就可以用了,因为VS在下载的同时,已经内联所需的库。

项目B调用了项目A的函数,项目A的函数用到了pthread;项目A在Cpp文件中#pragma comment(lib,“pthreadVC2.lib”)语句,实际在项目B编译时被运行的(项目A倒是用不上),动态加载pthreadVC2.lib。那么,根据语句中"pthreadVC2.lib"写法,一定是在项目B的根目录下寻找并加载pthreadVC2.lib文件。
所以,项目B中根目录下一定要放pthreadVC2.lib文件。
项目B通过NuGet程序包里下载pthreads库,并不能被项目A用到,所以不能这么做。

最后列出三个关键因素:

  • 测试程序(项目B)根目录下有 pthreadVC2.lib文件; 必须
  • 静态库-NuGet程序-加载pthreads库;必须
  • 静态库中 只有在用到多线程的cpp文件开头增加了如下语句 必须
 // 多线程   注意 这两句是加在静态库的一个cpp中的。
#include 
#pragma comment(lib,"pthreadVC2.lib")	

疑问5: 未解决
还是这个静态库用到了Jsoncpp,同样NuGet程序包-加载Jsoncpp库。同样也存在单独编译静态库OK,但是编译测试程序时就会报错的情况,也是链接错误。
最后我是编译了Jsoncpp源码解决的问题。

是否也可以#pragma comment(lib,“jsoncpp.lib”)解决呢?
以后在测试吧。

你可能感兴趣的:(C++,VS,c++)