Работа в сети и, в частности, выполнение http-запросов, в настоящее время является очень полезной функцией. Большое количество приложений, которые мы видим, имеют какой-то бэкэнд, с которым им необходимо взаимодействовать по самым разным причинам. Таким образом, каждая платформа предоставляет расширенные сетевые API как часть своего SDK, и написание фрагмента кода, который выдает HTTP-запрос, не является сложной задачей.

Однако при написании кроссплатформенного кода все становится немного сложнее (как это обычно бывает!). Все последние проекты, над которыми я работал, нацелены на несколько платформ и требуют выполнения http-запросов. Мы написали кроссплатформенные части кода, используя C и C++, а затем осталось решить, использовать ли стороннюю сетевую библиотеку C/C++, такую ​​как curl, или написать уровень абстракции (PAL) с сетевыми интерфейсами и реализовать их на каждой платформе.

В одном проекте мы выбрали первое, а в другом второе. Поскольку есть много вещей, которые следует учитывать при принятии решения о том, вводить PAL или нет, я оставлю это вне рамок этой статьи. Это могло бы стать предметом отдельного поста в блоге.

В этом посте я расскажу о технических деталях проекта, в котором мы используем libcurl, и объясню, как я создал libcurl для универсальной платформы Windows (UWP) для архитектуры x64.

Официально libcurl распространяется в виде пакетов с исходным кодом, но некоторые сторонние разработчики предоставляют бинарные пакеты для нескольких платформ. Вы можете найти различные доступные бинарные дистрибутивы на https://curl.haxx.se/download.html. Есть и другие дистрибутивы, созданные людьми, например, вот этот https://github.com/gcesarmza/curl-android-ios для iOS и Android.

Ниже приведены шаги, которые привели к сборке и запуску libcurl:

  1. Получить OpenSSL — у меня не работал WinSSL (ошибка подключения SSL). Вы можете получить его с http://slproweb.com/products/Win32OpenSSL.html — установите версию win64.
  2. Получите исходный код curl. Я получил его с github по адресу https://github.com/curl/curl.
  3. Используйте командную строку для запуска «C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat». Это может быть в другом месте для вас в соответствии с вашей версией Visual Studio. Важно запустить vcvars64, а не vcvars32. В противном случае вы получите сообщение об ошибке «Тип модуля модуля «X86» конфликтует с типом целевого компьютера «x64»».
  4. Перейдите туда, куда вы поместили curl, в подкаталог winbuild и запустите
    nmake /f Makefile.vc mode=dll ENABLE_SSPI=no ENABLE_IDN=no DEBUG=no MACHINE=X64 GEN_PDB=no ENABLE_IPV6=yes VC= 14 ENABLE_WINSSL=no WITH_SSL=static WITH_DEVEL=C:\OpenSSL-Win64
    Параметры VC и WITH_DEVEL могут различаться в зависимости от вашей версии VS и места установки OpenSSL.
  5. Артефакты находятся в подпапке builds под curl. Оставьте их или скопируйте куда угодно. Вы будете ссылаться на них из своего проекта.
  6. Откройте Visual Studio и создайте универсальное приложение Win.
  7. Добавьте путь поиска включения и ссылки на то место, куда вы скопировали артефакты завитка.
  8. Чтобы убедиться, что ваш исполняемый файл находит DLL-библиотеки curl и open ssl, вы можете либо добавить их расположение в переменную среды PATH, либо скопировать их в Visual Studio рядом с вашим исполняемым файлом, добавив библиотеки DLL в проект и щелкнув правой кнопкой мыши каждую DLL, выбрав свойства и задав для параметра Content значение YES
  9. Загрузите cacert.pem с http://curl.haxx.se/docs/caextract.html. Переименуйте его в curl-ca-bundle.crt (на основе этой страницы). Убедитесь, что ваш исполняемый файл может найти curl-ca-bundle.crt, чтобы ваш код мог его найти.
  10. curl вызовет ошибку компиляции, потому что шаблон универсального приложения Visual Studio по умолчанию включает winsock.h. Для решения этой проблемы я использовал макрос WIN32_LEAN_AND_MEAN, определенный для моего проекта. Другой способ, который должен сработать, — #include ‹winsock2.h› в pch.h проекта.
  11. После выполнения этих шагов у меня сработал следующий код. Он основан на примере, показанном на https://curl.haxx.se/libcurl/c/http-post.html:
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if (curl) {
 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
 curl_easy_setopt(curl, CURLOPT_URL, “https://whatever");
 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
 curl_easy_setopt(curl, CURLOPT_CAINFO, “curl-ca-bundle.crt”);
 res = curl_easy_perform(curl);
 /* always cleanup */
 curl_easy_cleanup(curl);
}

Надеюсь, этот пост поможет тем, кто, как и я, нуждается в libcurl для UWP. Я хотел бы получить обратную связь, поэтому дайте мне знать, если у вас есть какие-либо вопросы или комментарии по этому вопросу.