windows.h和 winsock2.h的相爱相杀的故事,在网络上广为流传,引发无数血案。各种作案场景,前置环境复杂纷繁,其中root原因和发生规律,以及解决方法,大致几种。今天就写上网上没有出现过的解决方法。
现场
前2天,一同事QT-Creator(msvc编译工具)开发一个远程socket通讯软件,包含 winsock2.h后,编译失败,各种重复winsock2.h里的结构体变量的重复包含。出错信息里,直接说明已经包含了winsock.h文件了,winsock.h里定义了很多和winsock2.h里重复的变量定义。
Root原因
在工程里其他地方包含或者间接包含了windows.h文件。而在windows.h文件里,默认会间接包含winsock.h文件。如果2个头文件包含的顺序如下,是可以幸免遇难的(侥幸逃过)。
#include<winsock2.h>
#include<windows.h>
因为winsock2.h里一个宏定义,可以防止包含winsock.h文件。
#define WINSOCKAPI /* Prevent inclusion of winsock.h in windows.h /
但如果是以下定义顺序,就必然重复包含winsock.h文件,而导致编译失败。
#include<windows.h>
#include<winsock2.h>
解决方法
1. 调整头文件的包含顺序,让winsock2.h文件首先被包含;
2. 使用以下宏定义来避免window.h间接加载winsock.h;
#define WIN32_LEAN_AND_MEAN
3. 以上方法,有失灵的时候
在我们的一个QT工程里,以上2种方法,无论怎么用,编译时,仍然是先包含windows.h,并且在包含之前,我们自以为OK的WIN32_LEAN_AND_MEAN定义,并没有生效。我大致分析了下原因,包含windows.h的地方有太多个,有自己新增的class,也有引入的第3方的代码。
答案揭晓:在project.pro文件里,添加
DEFINES += WIN32_LEAN_AND_MEAN
这样一次性的,就直接关闭windows.h间接包含winsock.h的可能。
总结
QT-Creator + MSVC编译工具的配对使用,似乎在目前的开发群体里还不多,网络上没有直接找到解决方法。但是一旦找到根本原因,解决方法是可以因地而变化的,不用限制在已有方案中。