Передайте дополнительные аргументы обратному вызову libcurl CURLOPT_READFUNCTION - PullRequest
1 голос
/ 07 ноября 2011

Программа

Считывает текстовый файл и отправляет его содержимое по электронной почте.

Оригинальный код (с помощью Sehe)

https://gist.github.com/1342118#file_test.cpp

Проблема:

Я пытаюсь запустить приложение несколько раз, используя потоки, используя разные текстовые файлы для каждого потока. Это означает, что я больше не могу использовать глобальный вектор, потому что поток 3 может добавлять / изменять этот вектор, пока поток 1 все еще работает над ним. Это означает, что эта линия становится проблематичной:

curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

Вызывает эту функцию:

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if (pooh->counter < text.size())
  {
      const std::string& data = text[pooh->counter];

      memcpy(ptr, data.data(), data.length());
      pooh->counter++; /* advance pointer */
      return data.length();
  }
  return 0; /* no more data left to deliver */
}

Как вы можете видеть, он использует глобально определенный вектор "текст". Я думал, что смогу это исправить, просто сделав вектор внутри этой функции (read_callback), но так как я использую многопоточность, имя файла больше не жестко запрограммировано, поэтому я в любом случае должен передать переменную.

Кажется, что Curl заполняет переменные, которые read_callback принимает автоматически, так как это делается?

Просто чтобы уточнить, вот что у меня сейчас:

std::vector<string> read_text(char* fname)
{
    std::ifstream myfile (fname);
    std::vector<string> text;

    std::string line;
    while (std::getline(myfile, line))
    {
        text.push_back(line + '\n');
    }

    return text;
}

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{

    std::vector<string> text;
    text = read_text(textfilename);

  struct WriteThis *pooh = (struct WriteThis *)userp;

  if(size*nmemb < 1)
    return 0;

  if (pooh->counter < text.size())
  {
      const std::string& data = text[pooh->counter];

      memcpy(ptr, data.data(), data.length());
      pooh->counter++; /* advance pointer */
      return data.length();
  }
  return 0; /* no more data left to deliver */
}

Но read_text не работает, потому что имя текстового файла не было передано функции.

1 Ответ

1 голос
/ 07 ноября 2011

Внимательно прочитайте еще раз curl_easy_setopt документация.Вы можете установить CURLOPT_READDATA на textfilename и разыграть userp, чтобы получить его внутри read_callback

edit

Ваш userpфактически используется;поэтому вы должны добавить textfilename в новое поле вашего WriteThis struct.Большинство функций обратного вызова принимают только одни пользовательские данные, но этого должно быть достаточно (поскольку вы можете упаковать в них произвольные данные).

...