Связывание Windows API - PullRequest
       6

Связывание Windows API

4 голосов
/ 04 августа 2010

Я использовал библиотеку ITK .Когда я написал пример программы с использованием этой библиотеки, я обнаружил следующие ошибки компоновщика.Как мы видим, все эти «неразрешенные» символы являются функциями Windows API, и эти функции Windows API использовались библиотекой ITK, а не моей программой.

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)

Эти ошибки вызвали у меня несколько вопросов.Для некоторых из них, я думаю, я знаю ответы, но мне нужно подтверждение, если я прав или нет.

  1. Эти функции Windows API используются в gdcmUtil.cpp (потому что там написано gdcmUtil.OBJ).Итак, компилятор компилирует gdcmUtil.cpp в (скажем) gdcmUtil.asm и ассемблер собирает его в gdcmUtil.obj.Поскольку при компиляции библиотеки мы не генерируем exe-файлы.Эти * .obj файлы не связаны с другими * .obj.Таким образом, символы Windows API все еще являются внешними символами для этого модуля и, таким образом, остаются нерешенными.Правильно?

  2. Кто создает файл * .LIB?Я имею в виду, что компилятор генерирует файл * .s, а Assembler генерирует файл * .obj, и мы не используем компоновщик.Итак, откуда мы взяли файл * .lib?Кто упаковал все файлы * .obj в файл * .lib?

  3. Как компилируются приложения Windows API (программы, написанные на C и использующие Windows API)?Я имею в виду, потому что это автономные приложения, как разрешаются эти символы WIN32 API?Предполагая, что я написал такую ​​программу, кто-нибудь может сказать мне, что мне нужно для успешной сборки приложения?

  4. Я знаю, что Windows API реализован в kernel32.dll, gdi32.dll, user32.dll (которая, в свою очередь, может импортировать некоторые другие dll, такие как wsock32.dll для сетевого API и т. д.), но вопрос в том, как использовать эти функции в функциях Windows API в программе на Си.Я имею в виду, как динамически связываться с этими DLL

  5. В моем стремлении найти ответ на мою проблему ошибок компоновщика.Я обнаружил, что должен добавить wsock32.lib (для WinSock 1.1) или ws2_32.lib (для WinSock 2) или snmpapi.lib к входу компоновщика.

    1. С каких пор Windows API статически связан?
    2. С каких пор Windows API поставляется в статических библиотеках (* .lib файлы)?
    3. В каком каталоге я могу найти все эти странные файлы * .lib?
  6. Теперь, есть ли альтернативное решение, кроме добавления файлов * .lib ввходные файлы компоновщика?потому что когда я использую новую библиотечную функцию ITK, я получаю новую ошибку компоновщика.Я должен найти в Google, к какому файлу * .lib относится этот конкретный символ (оконная функция API), и добавить этот файл * .lib к моему входу компоновщика.Это сводит меня с ума!Есть ли вменяемый способ?

1 Ответ

3 голосов
/ 04 августа 2010
  1. Да, все верно.
  2. Кто генерирует какой .lib файл? Статическая библиотека обычно генерируется утилитой lib. Библиотека для dll обычно генерируется компоновщиком.
  3. Вы разрешаете символы Windows, связываясь с нужными библиотеками.
  4. Опять же, связавшись с соответствующей библиотекой (например, kernel32.lib, gdi32.lib и user32.lib для трех упомянутых вами DLL).
  5. Это не связано статически. Вы ссылаетесь на библиотеку. В случае библиотеки для DLL (такой как перечисленные выше) компоновщик использует ее для встраивания записи в исполняемый файл, который сообщает загрузчику, какую DLL использовать для разрешения этих символов. Файлы .lib находятся в подкаталоге lib того места, где вы установили SDK (обычно это что-то вроде C:\Program Files\Microsoft SDKs\Windows\v6.0A. Обычно установщик SDK добавляет их там, где это необходимо, поэтому вам не нужно явно указывать этот каталог при ссылке из команды или в Visual Studio.
  6. Есть несколько, хотя остается открытым вопрос, действительно ли они являются улучшением. Можно использовать прагму, чтобы указать компоновщику использовать определенную библиотеку:

    # комментарий к прагме (lib, "ws2_32.lib")

Это особенно полезно в заголовке, если он использует функции, которые зависят от конкретной библиотеки.

...