सी ++ पुनर्वित्त हेडर फ़ाइलें (winsock2.h)


143

मैं हेडर फ़ाइलों को दो बार शामिल करने से कैसे रोकूँ? समस्या यह है कि मैं इसमें शामिल हूंमें MyClass.h और फिर मैं सम्मिलित कर रहा MyClass.h कई फाइलों में, तो यह कई बार शामिल है और परिभाषा त्रुटि तब होती है। कैसे बचाना है?

मैं गार्डों को शामिल करने के बजाय एक बार #pragma का उपयोग कर रहा हूं, और मुझे लगता है कि यह ठीक है।

MyClass.h:

// MyClass.h
#pragma once

#include <winsock2.h>

class MyClass
{

// methods
public:
 MyClass(unsigned short port);
 virtual ~MyClass(void);
};

संपादित करें: मुझे मिलने वाली त्रुटियों में से कुछ

c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(91) : warning C4005: 'AF_IPX' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(460) : see previous definition of 'AF_IPX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(124) : warning C4005: 'AF_MAX' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(479) : see previous definition of 'AF_MAX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(163) : warning C4005: 'SO_DONTLINGER' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(402) : see previous definition of 'SO_DONTLINGER'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(206) : error C2011: 'sockaddr' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(485) : see declaration of 'sockaddr'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing '}' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing ';' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2059: syntax error : 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C2143: syntax error : missing ';' before '}'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(518) : warning C4005: 'IN_CLASSA' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(287) : see previous definition of 'IN_CLASSA'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(524) : warning C4005: 'IN_CLASSB' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(293) : see previous definition of 'IN_CLASSB'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(530) : warning C4005: 'IN_CLASSC' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(299) : see previous definition of 'IN_CLASSC'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(541) : warning C4005: 'INADDR_ANY' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(304) : see previous definition of 'INADDR_ANY'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(543) : warning C4005: 'INADDR_BROADCAST' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(306) : see previous definition of 'INADDR_BROADCAST'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(577) : error C2011: 'sockaddr_in' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(312) : see declaration of 'sockaddr_in'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(132) : error C2011: 'fd_set' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(68) : see declaration of 'fd_set'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(167) : warning C4005: 'FD_SET' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(102) : see previous definition of 'FD_SET'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(176) : error C2011: 'timeval' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(111) : see declaration of 'timeval'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(232) : error C2011: 'hostent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(167) : see declaration of 'hostent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(245) : error C2011: 'netent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(180) : see declaration of 'netent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(252) : error C2011: 'servent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(187) : see declaration of 'servent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(264) : error C2011: 'protoent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(199) : see declaration of 'protoent'

4
आप पहले से ही एक बार #pragma का उपयोग कर रहे हैं, इसलिए इसे केवल एक बार ही शामिल किया जाना चाहिए।
नवीन

1
आपका कंपाइलर एक बार प्रज्ञा का समर्थन नहीं करता है?
श्वेतलोझर एंजेलोव

मैं विजुअल स्टूडियो 2008 का उपयोग कर रहा हूं, फिर दो बार क्यों शामिल है <winsock2.h>?
akif

1
यह
MyClass.h

5
winsock2 और winsock में आम संरचनाएं हैं। आपको उनमें से सिर्फ एक को शामिल करना है, दोनों को नहीं
स्वेतलोजर एंजेलोव

जवाबों:


234

यह समस्या तब होती है जब <windows.h>पहले शामिल होती है <winsock2.h>। पहले <windows.h>शामिल <winsock2.h>या परिभाषित करने के बाद अपनी सम्मिलित सूची को व्यवस्थित करने का प्रयास करें _WINSOCKAPI_:

#define _WINSOCKAPI_    // stops windows.h including winsock.h
#include <windows.h>
// ...
#include "MyClass.h"    // Which includes <winsock2.h>

यह भी देखें इस


मैं <windows.h> सहित बिल्कुल भी नहीं हूं, मुझे पता है कि <winsock2.h> मेरे लिए करता है।
akif

2
मेरे लिए आपका कोड केवल <winsock2.h>MSVC2008 में ठीक है । <windows.h>समावेश आपको प्रदान की गई समान संकलन त्रुटियों को उत्पन्न करता है।
pingw33n

क्या <windows.h> को stdafx.h में शामिल किया जा रहा है?
कॉलिन डेसमंड

1
इस समाधान ने मेरे लिए वीएस 2010 पर एसडीके 7.1 के साथ मुद्दा तय किया। धन्यवाद pingw33n!
adamfisk

मैं #include <winsock2.h> #include <ws2tcpip.h> #include <windows.h>क्रम में था और winsock2 प्राप्त कर रहा था, h फ़ाइल नहीं मिली। शामिल #define _WINSOCKAPI_ सभी 3 ऊपर अब भी वही त्रुटि शामिल हैं
एवा

75

जैसा कि दूसरों ने सुझाव दिया है, समस्या तब windows.hहै जब पहले शामिल किया गया हो WinSock2.h। क्योंकि windows.hशामिल है winsock.h। आप दोनों का उपयोग नहीं कर सकते हैं WinSock2.hऔर winsock.h

समाधान:

  • WinSock2.hपहले शामिल करें windows.h। पूर्वगामी हेडर के मामले में, आपको इसे वहां हल करना चाहिए। सरल परियोजना के मामले में, यह आसान है। हालाँकि बड़ी परियोजनाओं में (विशेष रूप से पोर्टेबल कोड लिखते समय, बिना पूर्व-निर्धारित हेडर के) यह बहुत कठिन हो सकता है, क्योंकि जब आपका हेडर WinSock2.hशामिल होता है, windows.hतो पहले से ही कुछ अन्य हेडर / कार्यान्वयन फ़ाइल से शामिल किया जा सकता है।

  • विस्तृत या परियोजना WIN32_LEAN_AND_MEANसे पहले परिभाषित करें windows.h। लेकिन यह आपके लिए आवश्यक कई अन्य सामानों को बाहर कर देगा और आपको इसे अपने द्वारा शामिल करना चाहिए।

  • विस्तृत या प्रोजेक्ट _WINSOCKAPI_से पहले परिभाषित करें windows.h। लेकिन जब आप शामिल होते हैं WinSock2.hतो आपको मैक्रो रिडिफाइनमेंट चेतावनी मिलती है।

  • अपने प्रोजेक्ट के लिए पर्याप्त होने के windows.hबजाय उपयोग करें (ज्यादातर मामलों में)। यह संभवत: अधिक संकलन समय में परिणाम देगा, लेकिन किसी भी त्रुटि / चेतावनी को हल करता है।WinSock2.hwinsock.h


14
WIN32_LEAN_AND_MEANमेरे लिए समाधान बहुत कुछ था
जोनाथन क्लॉटियर

_WINSOCK_समाधान के बारे में : यदि आप दोनों परिभाषाएँ समान हैं, तो आपको स्थूल पुनर्परिभाषित चेतावनी नहीं देनी चाहिए। आम बग यह है कि लोग किसी भी मूल्य को निर्धारित किए बिना परियोजना में परिभाषा जोड़ते हैं और खाली परिभाषा की अपेक्षा करते हैं। हालाँकि, यदि आप -D_WINSOCK_cmd लाइन में जोड़ते हैं, तो यह _WINSOCK_1 पर सेट हो जाएगा। खाली परिभाषा बनाने के लिए, पास -D_WINSOCK_=होना चाहिए।
पवन स्टेंकोव्स्की

यदि आप उपयोग करते हैं #define _WINSOCKAPI_, तो आपको #define _WINSOCK_DEPRECATED_NO_WARNINGSअपनी परिस्थितियों के आधार पर भी आवश्यकता हो सकती है।
लोरियन ब्रुने

16

ओह - विंडोज की बदसूरती ... ऑर्डर ऑफ शामिल हैं यहां महत्वपूर्ण हैं। Windows.h से पहले आपको winsock2.h को शामिल करना होगा। चूंकि windows.h संभवत: आपके precompiled शीर्ष लेख (stdafx.h) से शामिल है, आपको वहाँ से winsock2.h को शामिल करना होगा:

#include <winsock2.h>
#include <windows.h>

14

"हेडर गार्ड" का उपयोग करके:

#ifndef MYCLASS_H
#define MYCLASS_H

// This is unnecessary, see comments.
//#pragma once

// MyClass.h

#include <winsock2.h>

class MyClass
{

// methods
public:
    MyClass(unsigned short port);
    virtual ~MyClass(void);
};

#endif

2
मुझे लगता है कि मैं गलत हूं (अब तक 4 अपवोट्स), लेकिन मुझे लगता है कि गार्ड्स का उपयोग करना एक बार प्रज्ञा के समान है, आप उन दोनों को डालते हैं?
स्वितलॉजर एंजेलोव

1
खैर, मेरे पास एक बार #pragma है जो afaik एक ही हेडर गार्ड है
akif

2
@Angelov: हां, मैं यही कह रहा हूं कि वे वही चीजें हैं। समस्या मेरी हेडर फ़ाइलों के साथ नहीं है, लेकिन मुझे लगता है कि <winsock2.h> में हेडर गार्ड नहीं हैं या कुछ और हो सकता है।
akif

1
परिभाषा के अनुसार #pragma संकलक पर निर्भर (गैर-मानक) है। यह सभी कंपाइलरों पर काम नहीं कर सकता है। मुझे पता है कि दृश्य स्टूडियो एक बार #pargma को स्वीकार करता है। मुझे यकीन नहीं है कि अगर जीसीसी करता है। मुझे पता है कि गार्ड हमेशा काम करते हैं। मैं दोनों #प्रगमा का एक बार उपयोग करता हूं और अधिकतम सुरक्षा के लिए गार्ड शामिल करता हूं। ऐसा लगता है कि MSVC ने एक बार #pragma की हैंडलिंग को ऑप्टिमाइज़ किया है और gcc में शामिल गार्ड्स की हैंडलिंग को ऑप्टिमाइज़ किया है। मेरे मानक हेडर के साथ एकमात्र अंतर यह है कि #praga एक बार शामिल गार्ड के बाहर होता है।
KitsuneYMG 10

1
'#Pragma' कमांड ANSI मानक में एक मनमाना कार्यान्वयन-परिभाषित प्रभाव है। GNU C प्रीप्रोसेसर में, '#pragma' गेम 'दुष्ट' को चलाने का पहला प्रयास करता है; यदि वह विफल रहता है, तो यह गेम 'हैक' चलाने की कोशिश करता है; यदि यह विफल रहता है, तो यह हनोई के टॉवर को प्रदर्शित करने वाले GNU Emacs को चलाने की कोशिश करता है; यदि वह विफल रहता है, तो यह एक घातक त्रुटि की सूचना देता है। किसी भी मामले में, प्रीप्रोसेसिंग जारी नहीं है। - रिचर्ड एम। स्टालमैन, द जीएनयू सी प्रीप्रोसेसर, संस्करण 1.34
DevSolar

6

मैं इस समस्या में भाग गया जब तीसरे पक्ष के पैकेज को खींचने की कोशिश की जा रही थी, जो स्पष्ट रूप से विंडोज़ सहित था। इसमें हेडर की गड़बड़ थी। _WINSOCKAPI_प्रोजेक्ट स्तर पर परिभाषित करना उनके सूप के माध्यम से लुप्त होने और समस्याग्रस्त को ठीक करने की तुलना में बहुत आसान था (अधिक बनाए रखने का उल्लेख नहीं करना)।


1
Qt। DEFINES += _WINSOCKAPI_
Inpro

@phyatt: यदि आप ऐसा नहीं करेंगे, तो आपको जवाब में बदल देना चाहिए!
लीफ ग्रुएनवॉल्ड

@LeifGruenwoldt इसके लिए जाओ! मैं खुशी से मदद कर सकता है।
फिएट

6

वीएस 2015 में, निम्नलिखित काम करेगा:

#define _WINSOCKAPI_

जबकि निम्नलिखित नहीं होगा:

#define WIN32_LEAN_AND_MEAN

6

मैं जाँच की पुनरावर्ती भी शामिल है, मैं हेडर फाइल जो (रिकर्सिवली) शामिल देखा कुछ #include "windows.h"और #include "Winsock.h"है और एक लिखने #include "Winsock2.h"। इस फाइल में, मैंने #include "Winsock2.h"पहले शामिल के रूप में जोड़ा ।

धैर्य का मामला भी शामिल है, रंग-रूप में एक के बाद एक और इस आदेश की स्थापना, पहले #include "Winsock2.h"तो#include "windows.h"


5

मुझे यह लिंक windows.h और winsock2.h मिला, जिसमें एक विकल्प है जो मेरे लिए बहुत काम आया:

#define _WINSOCKAPI_    // stops windows.h including winsock.h
#include <windows.h>
#include <winsock2.h>

मुझे यह पता लगाने में समस्या हो रही थी कि समस्या कहाँ हुई थी लेकिन उस # शेड को जोड़कर मैं इसे समझ नहीं पाया।


4

मैं सिर्फ FILENAME_H का उपयोग नहीं करूंगा

#ifndef FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD
#define FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD

//code stuff
#endif // FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD

मैंने हमेशा पोस्टफिक्स गाइड का इस्तेमाल किया है। मैं कुछ साल पहले एक बहुत ही खराब कोड के आधार पर आया था जिसमें एक ही फ़ाइल नाम के साथ विभिन्न हेडर फाइलें थीं और इसमें गार्ड भी शामिल था। विचाराधीन फाइलों ने एक वर्ग को उसी नाम से परिभाषित किया था। यदि केवल नाम स्थान का उपयोग किया जाता था। कुछ परियोजनाओं को संकलित किया, कुछ को नहीं किया। अद्वितीय गार्ड का उपयोग हेडर और उनकी सामग्री को अलग करने में समाधान का एक हिस्सा था।

Windows पर Visual Studio के साथ Linux uuidgen -t पर guidegen.exe का उपयोग करें।


4

मैं एक ही मुद्दे में चला गया हूँ और यहाँ है जो मैंने अब तक खोजा है:

इस आउटपुट के टुकड़े से -

c: \ program files \ microsoft sdks \ windows \ v6.0a \ शामिल \ ws2def.h (91): C4005 चेतावनी: 'AF_IPX': मैक्रो पुनर्वित्त
c: \ program files \ microsoft sdks \ windows \ v6.0a \ शामिल \ winsock.h (460): 'AF_IPX' की पिछली परिभाषा देखें

-यह प्रतीत होता है कि आपके समाधान में ws2def.h और winsock.h दोनों को शामिल किया गया है।

यदि आप फ़ाइल ws2def.h को देखते हैं, तो यह निम्नलिखित टिप्पणी के साथ शुरू होता है -

/*++

Copyright (c) Microsoft Corporation. All rights reserved.

Module Name:

    ws2def.h

Abstract:

    This file contains the core definitions for the Winsock2
    specification that can be used by both user-mode and 
    kernel mode modules.

    This file is included in WINSOCK2.H. User mode applications
    should include WINSOCK2.H rather than including this file
    directly. This file can not be included by a module that also
    includes WINSOCK.H.

Environment:

    user mode or kernel mode

--*/

अंतिम पंक्ति पर ध्यान दें - "इस फ़ाइल को एक मॉड्यूल द्वारा शामिल नहीं किया जा सकता है जिसमें WINSOCK.H भी शामिल है।"

फिर भी कोड में बदलाव किए बिना समस्या को सुधारने की कोशिश की जा रही है।

मुझे पता है अगर यह समझ में आता है।


2

आपको हेडर गार्ड का उपयोग करना चाहिए।

उन लाइन को हेडर फ़ाइल के शीर्ष पर रखें

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

और सबसे नीचे

#endif

1
#pragma एक बार और गार्ड शामिल हैं वही चीजें हैं जो वे नहीं हैं?
akif

वे काफी समान नहीं हैं - हेडर गार्ड, प्रीप्रोसेसर स्तर पर फ़ाइल को फिर से शामिल करने से रोकेंगे, साथ ही वे स्पष्ट रूप से एक बार #pragma की तुलना में अधिक पोर्टेबल हैं।
टिमो जूसच

1
मेरा मतलब है कि वे एक ही उद्देश्य के लिए बनाए गए हैं :)
akif

2
#pragma एक बार गैर-मानक है, afaik
ntcong

2

#pragma onceफाइलन के पूर्ण पथ पर आधारित है। तो आपके पास जो संभावना है वह अलग-अलग निर्देशिकाओं में MyClass.h या Winsock2.h की दो समान प्रतियां हैं।


एक प्रतीकात्मक लिंक या NTFS जंक्शन भी सिस्टम को तोड़ने का कारण होगा।
Thomi

1

#pragma onceएमएस कंपाइलर पर भी परतदार है, और कई अन्य संकलक द्वारा समर्थित नहीं है। जैसा कि कई अन्य लोगों ने उल्लेख किया है, गार्ड का उपयोग करना जाने का रास्ता है। बिल्कुल उपयोग न करें #pragma once- यह आपके जीवन को बहुत आसान बना देगा।


3
दुर्भाग्य से, मैंने शून्य से अधिक बॉटेड देखा है जिसमें गार्ड शामिल हैं, या तो जहां एक टाइपो का अर्थ है कि गार्ड वास्तव में काम नहीं करता है, या जहां विभिन्न निर्देशिकाओं में एक ही नाम की फाइलें एक ही टोकन का उपयोग करती हैं, या जहां उपयोग किया गया टोकन एक डबल के साथ शुरू होता है अंडरस्कोर या अंडरस्कोर तब कैपिटल-लेटर (और इसलिए #pragma की तरह नॉन-पोर्टेबल है)। इसलिए स्वाभाविक रूप से गैर-पोर्टेबल कोड के लिए, winsock.h का उपयोग करने वाली किसी भी चीज़ की तरह, मैं #pragma द्वारा गहराई से अछूता था, एक बार जब आपने कहा कि यह परतदार था। यह कब विफल हो जाता है, इसके अलावा अन्य का समर्थन नहीं किया जा रहा है?
स्टीव जेसप

3
उपयोग करते समय #pragma once, कंपाइलर हेडर फ़ाइल नोड नाम को अद्वितीय आईडी के रूप में लेता है। यह विफल हो सकता है यदि आपके पास अपने स्रोत ट्री में प्रतीकात्मक लिंक या NTFS जंक्शन हैं (जितना आप सोच सकते हैं उससे अधिक आम है), या भले ही आपके पास किसी अन्य सिस्टम में समान नाम की एक फ़ाइल हो, जिसमें निर्देशिका शामिल है (मेरे साथ ऐसा पहले भी हो चुका है जब मैं कर चुका हूँ संस्करण 1 और एक ही लाइब्रेरी के संस्करण 2 में दो अलग-अलग सिस्टम में इंस्टॉल किए गए पथ शामिल हैं)। नीचे पंक्ति: मेरे लिए, मैं अधिक नियंत्रण रखना पसंद करता हूं, और कभी-कभी गीलेवेयर की गलती के साथ जीना पसंद करता हूं, बजाय इसके कि मेरे लिए यह करने के लिए एक संकलक पर भरोसा करें।
Thomi


1

मेरी परियोजना में (मैं वीएस 2008 SP1 का उपयोग करता हूं) अगले समाधान पर काम करता है:

शीर्ष लेख फ़ाइल:

//myclass.h
#pragma once
#define _WINSOCKAPI_
#include <windows.h>

सीपीपी वर्ग:

//myclass.cpp
#include "Util.h"
#include "winsock2class.h"
#pragma comment(lib, "Ws2_32.lib")

जहाँ #include "winsock2class.h" माध्य वर्ग है जिसने winsock2.h लागू किया है:

//winsock2class.h
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")

0

मैं वास्तव में एक मुद्दे पर भाग गया, जहां मुझे winsock2.h को पहली बार शामिल करना था, ऐसा लगता है कि इसमें अन्य पैकेजों के साथ अन्य मुद्दे भी हैं। उम्मीद है कि यह किसी ऐसे व्यक्ति के लिए मददगार हो, जो न केवल windows.h में, बल्कि सभी मुद्दों में शामिल हो।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.