不能同时包含WinSock2和Windows.h两个文件

15

我遇到了一个问题,就是无法同时包含两个文件。 现在,我知道我需要先包含Winsock2,然后是windows.h,或直接使用以下方式:

#define WIN32_LEAN_AND_MEAN

但是,我仍然有一些问题

我有一个名为XS.h的头文件,看起来像这样

#ifndef XS_H
#define XS_H

#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>

#endif

我在头文件Client.h中包含了XS.h

Client.h的引用如下:

#ifndef CLIENT_H
#define CLIENT_H

#include "XS.h"

XS.h是我在Client.h中唯一的包含文件,但我仍然会遇到错误(并且正如您所看到的,在windows.h之前已经包含了Winsock)。

我得到了大约78个错误,以下是其中的一些:

Error   90  error C3861: 'WSASetLastError': identifier not found    c:\program files (x86)\windows kits\8.0\include\um\ws2tcpip.h   703
Error   61  error C2375: 'WSAStartup' : redefinition; different linkage c:\program files (x86)\windows kits\8.0\include\um\winsock2.h   2296
Error   49  error C2375: 'send' : redefinition; different linkage   c:\program files (x86)\windows kits\8.0\include\um\winsock2.h   2026

我该如何解决这个问题?

谢谢!

编辑:我尝试使用#define _WINSOCKAPI_,但它并没有解决我的问题...... 我先包含了winsock.h,然后是windows.h,但它仍然对我产生错误。


在头文件中使用 #pragma once - A B
我建议在每个源文件中始终首先包含windows.h和windowsx.h(最好使用stdafx.h文件)。虽然我不确定它是否解决了这个特定的问题,但它可以减少很多混乱。 - PMF
我已经将Client.h的包含更改为以下内容:`#pragma once#include <winsock2.h>#include <ws2tcpip.h> #include "Chat.h"`但仍然无法正常工作,出现相同的错误... - Amit
这可能与以下内容相关:https://dev59.com/_XM_5IYBdhLWcg3wdyxg - user2249683
微软的“智能感知”不使用与编译器本身相同的分析引擎,因此它可以并且确实会为完全有效的代码输出“错误消息”。话虽如此,这听起来像是一个真正的问题,而不仅仅是Intellisense表面上的问题。在包含任何其他Windows API头文件之前,您应该始终包含windows.h。这是因为Microsoft头文件通常不包括它们所需的所有内容,即不遵循良好的编程实践。可以将<windows.h>强制包含,但这会重复导致问题的不良做法:最好修复源代码。 - Cheers and hth. - Alf
我已经编辑了我的帖子,以便更容易理解。 - Amit
4个回答

22
请确保 <windows.h> 没有包含 <winsock.h>(它提供了许多与 <winsock2.h> 相同的声明)。在我的系统中,<winsock2.h> 文件中有这行代码:
#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */

_WINSOCKAPI_ 包含宏可能是内部实现细节,但作为实际解决方案,我会依赖它,只需在包含 <windows.h> 之前定义此符号,例如在编译器调用中(对于 IDE 来说,这意味着在项目设置中)。

或者你可以尝试在 始终在 <windows.h> 之前包含 <winsock2.h>, 以建立相关的包含宏,无论其是什么(但我认为这比假定上述宏是实际上被定义的更加脆弱);

或者您可以定义WIN32_LEAN_AND_MEAN,它会防止<windows.h>包含<winsock.h>,但也会防止一些其他头文件的包含(在我的系统上列出的这些头文件为<cderr.h><dde.h><ddeml.h><dlgs.h><lzexpand.h><mmsystem.h><nb30.h><rpc.h><shellapi.h><winperf.h><wincrypt.h><winefs.h><winscard.h><winspool.h><ole2.h><commdlg.h>)。我不建议依赖WIN32_LEAN_AND_MEAN优化来保证正确性

即最小:

#undef UNICODE
#define UNICODE
#undef _WINSOCKAPI_
#define _WINSOCKAPI_
#include <windows.h>
#include <winsock2.h>

auto main()
    -> int
{}

结果发现,我在主源文件中包含了windows.h,导致了问题,然后 WINSOCKAPI 修复了其他错误...谢谢! - Amit
“WIN32_LEAN_AND_MEAN”不是最佳选择吗?为什么它不起作用?在使用它时,包含顺序是什么? - Sandburg
显然没有明确的“最佳”选择。例如,考虑使用依赖于<windows.h>的第三方头文件,这会导入一个或多个被WIN32_LEAN_AND_MEAN排除的头文件。原始文档仅将其定义为“参考Windows.H以确定将要排除的文件”。因此,这两种方法都基于查找MS头文件代码,而该代码可能会发生变化。如果不排除列出的头文件没有问题,那么可以同时使用这两种方法。 - Cheers and hth. - Alf

5

我确保在任何#include "windows.h""#include "Winsock.h"之前先加入#include "Winsock2.h",这解决了问题。

只需要耐心地一个接一个地查看包含的内容并建立这个顺序,首先是#include "Winsock2.h",然后是#include "windows.h"

我检查了递归包含文件,发现一些头文件递归地包含了#include "windows.h""#include "Winsock.h",于是在这些文件中我添加了#include "Winsock2.h"作为第一个包含文件。


我知道这是一个旧帖子,但上面的解决方案并不总是有效。有第三方库会包含windows.h文件,而你可能不知道。一个让我头痛的好例子是Qt的头文件QSGGeometry。 我的偏好是为任何(CMake)模块定义WIN32_LEAN_AND_MEAN,这些模块不需要winsock。 - Rich von Lehe

1

将包含文件添加到pch.h中:

// TODO: add headers that you want to pre-compile here
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

0
关键是设置预编译定义 WIN32_LEAN_AND_MEAN。
你需要设置它,并重新检查包含。
因为没有设置它,MFC框架会抛出一个消息 "#error WINDOWS.H already included. MFC apps must not #include "。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接