【问题标题】:C libcurl get output into a stringC libcurl 将输出转换为字符串
【发布时间】:2011-01-20 17:40:20
【问题描述】:

我想将这个 curl 函数的结果存储在一个变量中,我该怎么做?

#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
    res = curl_easy_perform(curl);

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return 0;
}

谢谢,我是这样解决的:

#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>

function_pt(void *ptr, size_t size, size_t nmemb, void *stream){
    printf("%d", atoi(ptr));
}

int main(void)
{
  CURL *curl;
  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function_pt);
    curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
  system("pause");
  return 0;
}

【问题讨论】:

标签: c libcurl


【解决方案1】:

通过阅读此处的手册:http://curl.haxx.se/libcurl/c/curl_easy_setopt.html 我认为您需要多次调用 CURL_SETOPT,第一个是您要处理的 URL,第二个类似于:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function_ptr);

其中 function_ptr 匹配此签名:

size_t function( void *ptr, size_t size, size_t nmemb, void *stream)

这里发生的是你表示一个回调函数,当它有一些输出要从你调用的任何传输中写入时,libcurl 将调用它。您可以让它自动写入文件,或将指针传递给将处理输出本身的函数。使用此功能,您应该能够将各种输出字符串组合成一个片段,然后在您的程序中使用它们。

我不确定您可能需要设置哪些其他选项/还有哪些会影响您希望应用的行为方式,因此请仔细查看该页面。

【讨论】:

    【解决方案2】:

    您可以使用curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, myfunc);设置回调函数来接收传入的数据块

    回调将采用用户定义的参数,您可以使用 curl_easy_setopt(curl, CURLOPT_WRITEDATA, p) 设置该参数

    这是一段代码,它将缓冲区 struct string {*ptr; len} 传递给回调函数,并在每次调用时使用 realloc() 增大该缓冲区。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <curl/curl.h>
    
    struct string {
      char *ptr;
      size_t len;
    };
    
    void init_string(struct string *s) {
      s->len = 0;
      s->ptr = malloc(s->len+1);
      if (s->ptr == NULL) {
        fprintf(stderr, "malloc() failed\n");
        exit(EXIT_FAILURE);
      }
      s->ptr[0] = '\0';
    }
    
    size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
    {
      size_t new_len = s->len + size*nmemb;
      s->ptr = realloc(s->ptr, new_len+1);
      if (s->ptr == NULL) {
        fprintf(stderr, "realloc() failed\n");
        exit(EXIT_FAILURE);
      }
      memcpy(s->ptr+s->len, ptr, size*nmemb);
      s->ptr[new_len] = '\0';
      s->len = new_len;
    
      return size*nmemb;
    }
    
    int main(void)
    {
      CURL *curl;
      CURLcode res;
    
      curl = curl_easy_init();
      if(curl) {
        struct string s;
        init_string(&s);
    
        curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
        res = curl_easy_perform(curl);
    
        printf("%s\n", s.ptr);
        free(s.ptr);
    
        /* always cleanup */
        curl_easy_cleanup(curl);
      }
      return 0;
    }
    

    【讨论】:

    • 不错。如果所有这些size_t(除了len 本身)都被声明为const,那就更好了。
    • 对于 C++ std::string 转到 here
    【解决方案3】:

    以下答案是 C++ 方法,使用std::string,而不是以空字符结尾的字符串。它仍然使用回调函数(没有办法绕过它),但也使用 try/catch 处理分配错误。

    #include <iostream>
    #include <string>
    #include <curl/curl.h>
    
    size_t CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s)
    {
        size_t newLength = size*nmemb;
        try
        {
            s->append((char*)contents, newLength);
        }
        catch(std::bad_alloc &e)
        {
            //handle memory problem
            return 0;
        }
        return newLength;
    }
    int main()
    {
        CURL *curl;
        CURLcode res;
    
        curl_global_init(CURL_GLOBAL_DEFAULT);
    
        curl = curl_easy_init();
        std::string s;
        if(curl)
        {
    
            curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
    
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //only for https
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //only for https
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
            curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); //remove this to disable verbose output
    
    
            /* Perform the request, res will get the return code */
            res = curl_easy_perform(curl);
            /* Check for errors */
            if(res != CURLE_OK)
            {
                fprintf(stderr, "curl_easy_perform() failed: %s\n",
                        curl_easy_strerror(res));
            }
    
            /* always cleanup */
            curl_easy_cleanup(curl);
        }
    
        std::cout<<s<<std::endl;
    
        std::cout<< "Program finished!" << std::endl;
    }
    

    【讨论】:

    • 我认为 std::string::append 可以让回调函数简单很多。
    • @rnickb 你是对的; s-&gt;append((char*)contents. nmemb); 与我完美配合,更简洁。此外,回调的official function signature 有一个char* 作为第一个参数,因此您可以使用它并省略强制转换。最后,s-&gt;resize() 实际上初始化了新分配的空间。反正你要覆盖它,s-&gt;reserve() 会更有效率。
    • 这对我帮助很大。您能否也举一个如何使用 HTTP POST 的示例:-)
    【解决方案4】:

    这是来自alex-jasmin 的已接受答案的 C++ 风格

    #include <iostream>
    #include <string>
    #include <curl/curl.h>
    
    size_t writefunc(void *ptr, size_t size, size_t nmemb, std::string *s) 
    {
      s->append(static_cast<char *>(ptr), size*nmemb);
      return size*nmemb;
    }
    
    int main(void)
    {
      CURL *curl = curl_easy_init();
      if (curl)
      {
        std::string s;
    
        curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
    
        CURLcode res = curl_easy_perform(curl);
    
        std::cout << s << std::endl;
    
        /* always cleanup */
        curl_easy_cleanup(curl);
      }
      return 0;
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-09
      • 1970-01-01
      相关资源
      最近更新 更多