C libcurl nhận đầu ra thành một chuỗi


94

Tôi muốn lưu trữ kết quả của hàm curl này trong một biến, làm thế nào tôi có thể làm như vậy?

#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;
}

cảm ơn, tôi đã giải quyết nó như thế này:

#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;
}

1
Chỉ cần chỉ ra trong giải pháp của bạn trong function_pt (), bạn đang chuyển đổi chuỗi trong ptr thành số nguyên để chuyển đổi nó trở lại thành chuỗi trong đầu ra. Bạn có thể xuất chuỗi trực tiếp (và xem toàn bộ phản hồi).
zzz

2
đây là một liên kết đến cURL dụ curl.haxx.se/libcurl/c/getinmemory.html
lafferc

1
CURLcode res;không được sử dụng
fnc12

cùng một câu hỏi nhưng đối với C ++ thay vì c đi đến đây: Lưu cURL nội dung kết quả vào một chuỗi trong C ++
Trevor Boyd Smith

Câu trả lời:


114

Bạn có thể đặt chức năng gọi lại để nhận các phần dữ liệu đến bằng cách sử dụng curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, myfunc);

Lệnh gọi lại sẽ nhận một đối số do người dùng xác định mà bạn có thể đặt bằng cách sử dụng curl_easy_setopt(curl, CURLOPT_WRITEDATA, p)

Đây là một đoạn mã chuyển một bộ đệm struct string {*ptr; len}cho hàm gọi lại và phát triển bộ đệm đó trên mỗi cuộc gọi bằng cách sử dụng 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;
}

1
Đẹp. Thậm chí còn đẹp hơn nếu tất cả những thứ đó size_t(ngoài lenchính nó) sẽ được khai báo const.
alk

1
cho C ++, std::stringhãy truy cập vào đây
Trevor Boyd Smith

34

Câu trả lời sau đây là cách C ++ để làm điều đó std::string, thay vì chuỗi kết thúc bằng null. Nó vẫn sử dụng một hàm gọi lại (không có cách nào xung quanh nó), nhưng cũng xử lý lỗi cấp phát bằng cách sử dụng 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;
}

Tôi nghĩ rằng std :: string :: append có thể làm cho hàm gọi lại đó đơn giản hơn rất nhiều.
Ryan Burn

@rnickb Bạn nói đúng; s->append((char*)contents. nmemb);hoạt động hoàn hảo với tôi và ngắn gọn hơn. Ngoài ra, chữ ký hàm chính thức cho lệnh gọi lại có char*đối số là đối số đầu tiên, vì vậy bạn có thể sử dụng đối số đó và bỏ qua quá trình truyền. Và cuối cùng, s->resize()thực sự khởi tạo không gian mới được cấp phát. Vì bạn vẫn sắp ghi đè nó, s->reserve()sẽ hiệu quả hơn.
Jeinzi,

Điều này đã giúp tôi rất nhiều. Bạn cũng có thể cho một ví dụ về cách làm điều đó với HTTP POST không :-)
Lord Wolfenstein

9

Từ việc đọc hướng dẫn tại đây: http://curl.haxx.se/libcurl/c/curl_easy_setopt.html Tôi nghĩ bạn cần một vài lệnh gọi tới CURL_SETOPT, lệnh đầu tiên là URL bạn muốn xử lý, lệnh thứ hai là:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function_ptr);

Trường hợp function_ptr khớp với chữ ký này:

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

Điều xảy ra ở đây là bạn biểu thị một hàm gọi lại mà libcurl sẽ gọi khi nó có một số đầu ra để ghi từ bất kỳ chuyển giao nào bạn đã gọi. Bạn có thể làm cho nó tự động ghi vào một tệp hoặc chuyển nó một con trỏ đến một hàm sẽ tự xử lý đầu ra. Sử dụng chức năng này, bạn sẽ có thể tập hợp các chuỗi đầu ra khác nhau thành một đoạn và sau đó sử dụng chúng trong chương trình của bạn.

Tôi không chắc bạn có thể phải đặt các tùy chọn nào khác / những tùy chọn nào khác ảnh hưởng đến cách bạn muốn ứng dụng của mình hoạt động, vì vậy hãy xem kỹ trang đó.


0

Đây là hương vị C ++ của câu trả lời được chấp nhận từ alex-jasmin

#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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.