How to avoid error "LNK2001 unresolved external" by using DEFINE_GUID

Article translations Article translations
Article ID: 130869 - View products that this article applies to.
This article was previously published under Q130869
Expand all | Collapse all

On This Page

SUMMARY

In Microsoft Visual C++, if the version of the compiler is older than a specific version, a GUID must be initialized exactly once. For this reason, there are two different versions of the DEFINE_GUID macro. One version just declares an external reference to the symbol name. The other version actually initializes the symbol name to the value of the GUID. If you receive an LNK2001 error for the symbol name of the GUID, the GUID was not initialized.

Note The DEFINE_GUID macro in the guiddef.h header file declares a GUID. To also define the GUID, include the INITGUID.H header file in the source file where the GUID should be defined.

You can make sure your GUID gets initialized in one of two ways:
  • If you are using precompiled header files, include the INITGUID.H header file before defining the GUID in the implementation file where it should be initialized. (AppWizard-generated MFC projects use precompiled headers by default.)
  • If you are not using precompiled headers, define INITGUID before including OBJBASE.H. (OBJBASE.H is included by OLE2.H.)
Note If the version of the compiler is newer than a specific version, when you are using precompiled headers, you can include the INITGUID.H header file in a single header file that includes other header files. This will cause the GUID to be defined in all the source files where this header file is included. You will not receive an LNK2001 error even if a symbol is defined multiple times. This is because a DECLSPEC_SELECTANY keyword is used in the DEFINE_GUID macro. This keyword makes sure that the linker will correctly handle this multiple definition.

MORE INFORMATION

If the version of the compiler is older than a specific version

Here is the definition of DEFINE_GUID as it appears in OBJBASE.H:
      #ifndef INITGUID
      #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, \ 
                                b4, b5, b6, b7, b8)
          EXTERN_C const GUID FAR name
      #else

      #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, \ 
                                b4, b5, b6, b7, b8)
         EXTERN_C const GUID name \ 
            = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
      #endif // INITGUID
				
Note that if the symbol INITGUID is not defined, DEFINE_GUID simply defines an external reference to the name.

In INITGUID.H, you find (among other things):
      #undef DEFINE_GUID

      // Other code . . .

      #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, \ 
                                b4, b5, b6, b7, b8)
         EXTERN_C const GUID __based(__segname("_CODE")) name \ 
                  = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
				
By including INITGUID.H after OBJBASE.H, DEFINE_GUID is modified to actually initialize the GUID.

NOTE: It is important to make sure that this is done exactly once for each DLL or EXE. If you try to initialize the GUID in two different source files and then link them together, you get this error:
LNK2005 <symbol> already defined.

If the version of the compiler is newer than a specific version

The definition of DEFINE_GUID as it appears in OBJBASE.H is as follows.
#ifdef INITGUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
        EXTERN_C const GUID DECLSPEC_SELECTANY name \
                = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
#else
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    EXTERN_C const GUID FAR name
#endif // INITGUID
The definition of the DECLSPEC_SELECTANY keyword in Guiddef.h is as follows.
#ifndef DECLSPEC_SELECTANY
#if (_MSC_VER >= 1100)
#define DECLSPEC_SELECTANY  __declspec(selectany)
#else
#define DECLSPEC_SELECTANY
#endif
#endif
Note If the DECLSPEC_SELECTANY keyword is used in OBJBASE.H, the initialization code of the unreferenced object will be discarded. Therefore, if the version of the compiler is newer than a specific version, the error does not occur.

Properties

Article ID: 130869 - Last Review: April 11, 2007 - Revision: 4.0
APPLIES TO
  • Microsoft Visual C++ 2.0 Professional Edition
  • Microsoft Visual C++ 2.1
  • Microsoft Visual C++ 4.0 Standard Edition
  • Microsoft Visual C++ 4.1 Subscription
  • Microsoft Visual C++ 4.2 Enterprise Edition
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 6.0 Enterprise Edition
  • Microsoft Visual C++ 4.2 Professional Edition
  • Microsoft Visual C++ 5.0 Professional Edition
  • Microsoft Visual C++ 6.0 Professional Edition
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
Keywords: 
kbhowto kbarttypeinf KB130869

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com