views:

53

answers:

1

Hello,

I was using a ITK library. When I wrote a sample program using this library, I've got following linker errors. As we can see these all "unresolved" symbols are Windows API functions and these windows API functions were used by ITK library and not my program.

Error   1   error LNK2019: unresolved external symbol _SnmpUtilVarBindFree@4 referenced in function "int __cdecl gdcm::GetMacAddrSys(unsigned char *)" (?GetMacAddrSys@gdcm@@YAHPAE@Z)  C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)
Error   2   error LNK2019: unresolved external symbol _SnmpUtilOidNCmp@12 referenced in function "int __cdecl gdcm::GetMacAddrSys(unsigned char *)" (?GetMacAddrSys@gdcm@@YAHPAE@Z) C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)
Error   3   error LNK2019: unresolved external symbol _SnmpUtilOidCpy@8 referenced in function "int __cdecl gdcm::GetMacAddrSys(unsigned char *)" (?GetMacAddrSys@gdcm@@YAHPAE@Z)   C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)
Error   4   error LNK2019: unresolved external symbol _WSAStartup@8 referenced in function "int __cdecl gdcm::GetMacAddrSys(unsigned char *)" (?GetMacAddrSys@gdcm@@YAHPAE@Z)   C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)
Error   5   error LNK2019: unresolved external symbol __imp__UuidCreate@4 referenced in function "private: static bool __cdecl gdcm::Util::GenerateUUID(unsigned char *)" (?GenerateUUID@Util@gdcm@@CA_NPAE@Z)  C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)
Error   6   error LNK2019: unresolved external symbol _gethostbyname@4 referenced in function "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl gdcm::Util::GetIPAddress(void)" (?GetIPAddress@Util@gdcm@@CA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)  C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)
Error   7   error LNK2019: unresolved external symbol _gethostname@8 referenced in function "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl gdcm::Util::GetIPAddress(void)" (?GetIPAddress@Util@gdcm@@CA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)    C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)
Error   8   error LNK2019: unresolved external symbol _WSACleanup@0 referenced in function "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl gdcm::Util::GetIPAddress(void)" (?GetIPAddress@Util@gdcm@@CA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) C:\Projects\sampleProject\bin\itkgdcm.lib(gdcmUtil.obj)

These errors have raised few questions in my mind. For some of them I think I know the answers but I need confirmation if I'm right or wrong.

  1. These Windows API functions are used in gdcmUtil.cpp (because it says gdcmUtil.obj). So, compiler compiles gdcmUtil.cpp to (say)gdcmUtil.asm and it is assembler assembles it to gdcmUtil.obj. Since while compiling the library we are not generating any exe files. These *.obj files aren't linked against any other *.obj. So, windows API symbols are still external symbols for that module and thus left unresolved. Right?

  2. Who is generating the *.LIB file? I mean compiler is generating *.s file and Assembler is generating *.obj file and we are not using linker. So, from where did we get *.lib file? Who packed all *.obj files to a *.lib file?

  3. How are Windows API applications (programs that are written in C and use Windows API) are compiled? I mean, because its a standalone applications how are these WIN32 API symbols resolved? Assuming, I've written such program can anyone tell me what do I need to sucessfully build application?

  4. I know that Windows API is implemented in kernel32.dll, gdi32.dll, user32.dll (which may in turn import some other dlls like wsock32.dll for networking API etc.) but the question is How to use these functions in Windows API functions in a C program. I mean how to dynamically link against these DLLs

  5. In my quest to find answer to my problem of Linker errors. I discovered that I must add wsock32.lib (for WinSock 1.1) or ws2_32.lib(for WinSock 2) or snmpapi.lib to Linker Input.

    1. Since when Windows API is being statically linked?
    2. Since when windows API is being shipped in static libraries (*.lib files)?
    3. In which directory can I find all these strange *.lib files?
  6. Now, Is there any alternative solution other than adding *.lib files to linker input files? because when ever I use some new ITK library function, I get a new linker error. I've to Google to find in which *.lib file this specific symbol (window api function) belongs to then add that *.lib file to my linker input. Its driving me crazy! Is there any sane way?

+1  A: 
  1. Yes, that's right.
  2. Who is generating what .lib file? A static library is normally generated by the lib utility. A library for a dll is normally generated by the linker.
  3. You resolve Windows symbols by linking with the right libraries.
  4. Again, by linking against the appropriate library (e.g., kernel32.lib, gdi32.lib and user32.lib for the three DLLs you mentioned).
  5. It's not statically linked. You link against the library. In the case of a library for a DLL (such as those listed above) the linker uses that to embed a record into the executable that tells the loader which DLL to use to resolve those symbols. The .lib files are in the lib subdirectory of wherever you installed the SDK (typically something like C:\Program Files\Microsoft SDKs\Windows\v6.0A. Normally the SDK installer will add those where necessary so you don't have to explicitly specify that directory when linking from the command line or within Visual Studio.
  6. There are a few, though it's open to question whether they're really an improvement. One possibility is to use a pragma to tell the linker to use a particular library:

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

This is particularly useful in a header if it uses functions that depend on a particular library.

Jerry Coffin
claws