#c #curl #libcurl #void-pointers
Вопрос:
Я пытаюсь реализовать некоторые функции curl и curlcpp для небольшого проекта.
До сих пор я реализовал несколько функций, но теперь я хочу добавить функциональность. Идея состоит в том, чтобы хранить в буфере отправленные и полученные данные, чтобы позже я мог получить доступ:
- Отправленные Данные
- Отправленные заголовки
- Полученные Данные
- Полученные заголовки
Я знаю, что есть функция CURLOPT_WRITEFUNCTION, но это работает только для данных ответа, и мне тоже нужны выходные данные/заголовки. Функция CURLOPT_DEBUGFUNCTION выглядит так, как будто она работает для меня, но я не могу настроить ее на CPP.
Вот пример кода моего класса:
class CurlCPPClient
{
private:
...
int trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr);
curl::curl_easy curl_easy;
std::string raw_data;
public:
...
}
CurlCPPClient::CurlCPPClient()
{
curl_easy.add<CURLOPT_DEBUGFUNCTION>(this->trace_data);
}
int CurlCPPClient::trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr)
{
std::string frame_info(data);
switch(type)
{
case CURLINFO_HEADER_OUT:
case CURLINFO_DATA_OUT:
raw_data = frame_info;
break;
case CURLINFO_HEADER_IN:
case CURLINFO_DATA_IN:
raw_data = frame_info;
break;
default:
break;
}
return 0;
}
У меня проблемы с компилятором при установке указателя функции на trace_data. Я получаю «ошибка C3867» и «ошибка C2228» с помощью: this->trace_data, this.trace_data, trace_data.
Если я не использую trace_data в качестве метода своего класса, я могу вызвать его, но я не могу сохранить информацию о члене, чтобы получить к ней доступ позже в другой части класса.
Ответ №1:
libcurl ожидает автономные функции в стиле C для своих обратных вызовов. Вы не можете использовать метод нестатического класса для обратного вызова.
Объявите свой trace_data()
метод статическим. Вы можете использовать CURLOPT_DEBUGDATA
для передачи this
указателя CurlCPPClient
объекта в параметр метода userptr
.
class CurlCPPClient
{
private:
...
static int trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr);
curl::curl_easy curl_easy;
std::string raw_data;
public:
...
}
CurlCPPClient::CurlCPPClient()
{
curl_easy.add<CURLOPT_DEBUGFUNCTION>(amp;CurlCPPClient::trace_data);
curl_easy.add<CURLOPT_DEBUGDATA>(this);
}
int CurlCPPClient::trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr)
{
CurlCPPClient *pThis = static_cast<CurlCPPClient*>(userptr);
std::string frame_info(data, size);
switch(type)
{
case CURLINFO_HEADER_OUT:
case CURLINFO_DATA_OUT:
pThis->raw_data = frame_info;
break;
case CURLINFO_HEADER_IN:
case CURLINFO_DATA_IN:
pThis->raw_data = frame_info;
break;
default:
break;
}
return 0;
}
В качестве альтернативы используйте CURLOPT_DEBUGDATA
для передачи только raw_data
элемента в обратный вызов:
class CurlCPPClient
{
private:
...
static int trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr);
curl::curl_easy curl_easy;
std::string raw_data;
public:
...
}
CurlCPPClient::CurlCPPClient()
{
curl_easy.add<CURLOPT_DEBUGFUNCTION>(amp;CurlCPPClient::trace_data);
curl_easy.add<CURLOPT_DEBUGDATA>(amp;raw_data);
}
int CurlCPPClient::trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr)
{
std::string *pRawData = static_cast<std::string*>(userptr);
std::string frame_info(data, size);
switch(type)
{
case CURLINFO_HEADER_OUT:
case CURLINFO_DATA_OUT:
*pRawData = frame_info;
break;
case CURLINFO_HEADER_IN:
case CURLINFO_DATA_IN:
*pRawData = frame_info;
break;
default:
break;
}
return 0;
}