четверг, 13 июня 2024 г.

Использование функции CURL в CPLUPLUS при считывании страниц HTML

 При использовании функции curl не известно какой длины будет читаемая страница. Поэтому используют режим 

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,ФУНКЦИЯ ...
curl читает страницу блоками постоянной длины и передает прочитанный буфер указанной ФУНКЦИИ. 
Она же обязана добавить блок к результату. 
В C++ многие используют лямда функцию вместо ссылки на реальную функцию. При выполнения готового примера 
я столкнулся с аварийным завершением программы: exit value 1073 741 819. В Windows 
это означает защита доступа к памяти!
После длительных поисков я нашел такой текст:
--------------------------------------------------------------------------------------

Curl_easy_setopt документирован сигнатурой

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);

где параметр может быть одним из нескольких типов в зависимости от опции. Очевидно, что (как C API, где C не имеет перегрузки) он должен делать что-то странное, и это подтверждается рассмотрением the source, где мы видим, что Curl_easy_setopt реализован с помощью varargs.

CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);

Таким образом, проблема с передачей лямбды в Curl_easy_setopt заключается в том, что она передается как есть, поскольку Curl_easy_setopt говорит, что может принимать объекты любого типа. Фактический объект, представленный лямбда-выражением, представляет собой всего лишь структуру захватов; в этом случае вы просто передаете пустой объект структуры в функцию Curl_easy_setopt, когда она ожидает указатель на функцию. Наступает хаос.

Лямбда-выражения без захватов можно явно преобразовать в указатели на функции с помощью унарного +.

                                                                                              // v one char fix! 

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](void *buffer, size_t size, size_t count, std::string *stream) -> size_t { auto s_size = size * count; stream->append((char *)buffer, 0, s_size); return s_size; });

Это преобразование также может происходить неявно, но curl_easy_setopt не предоставляет никакой информации о типе и, следовательно, не запускает преобразование автоматически.

***********************************************************************

Как только я поставил этот плюсик ВСЕ заработало!

 
  

X-Plane 11, 12 - любитель, Фото любитель со стажем

Постоянные читатели

Архив блога