C libcurl bir dizgeye çıktı alır


98

Bu curl fonksiyonunun sonucunu bir değişkende saklamak istiyorum, bunu nasıl yapabilirim?

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

teşekkürler, bunu şu şekilde çözdüm:

#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
Sadece function_pt () içindeki çözümünüzde belirtmek için, çıktıdaki dizgeyi tekrar dizgeye dönüştürmek için ptr'deki dizeyi tam sayıya dönüştürüyorsunuz. Dizeyi doğrudan çıkarabilir (ve tam yanıtı görebilirsiniz).
zzz

2
işte cURL örneğinin bir bağlantısı curl.haxx.se/libcurl/c/getinmemory.html
lafferc

1
CURLcode res;kullanılmıyor
fnc12

1
aynı soru ama C ++ için c yerine buraya gidin: cURL içeriği sonucunu C ++ 'da bir dizeye kaydedin
Trevor Boyd Smith

Yanıtlar:


117

Kullanarak, gelen veri parçalarını almak için bir geri arama işlevi ayarlayabilirsiniz. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, myfunc);

Geri arama, kullanarak ayarlayabileceğiniz kullanıcı tanımlı bir bağımsız değişken alacaktır. curl_easy_setopt(curl, CURLOPT_WRITEDATA, p)

Burada struct string {*ptr; len}, geri arama işlevine bir arabellek geçiren ve realloc () kullanarak her çağrıda bu arabelleği büyüten bir kod parçası var .

#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
Güzel. Tüm bunların size_t( lenkendisi dışında ) beyan edilmesi daha da güzel const.
alk

2
C ++ std::stringiçin buraya
Trevor Boyd Smith

35

Aşağıdaki yanıt, std::stringboş sonlandırılmış dizge yerine C ++ ile bunu yapmanın yoludur . Hala bir geri arama işlevi kullanıyor (bunun etrafında bir yol yok), ancak dene / yakala kullanarak ayırma hatasını da ele alıyor.

#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'in geri arama işlevini çok daha basit hale getirebileceğini düşünüyorum.
Ryan Burn

@rnickb Haklısın; s->append((char*)contents. nmemb);benimle kusursuz çalışıyor ve daha özlü. Ayrıca, geri arama için resmi işlev imzasının bir char*ilk bağımsız değişkeni vardır, bu nedenle bunu kullanabilir ve dönüştürmeyi atlayabilirsiniz. Ve son olarak, s->resize()yeni tahsis edilen alanı gerçekten başlatır. Yine de üzerine yazmak üzereyken, s->reserve()daha verimli olacaktır.
Jeinzi

Bu bana çok yardımcı oldu. Ayrıca HTTP POST ile nasıl yapılacağına dair bir örnek verebilir misiniz lütfen :-)
Lord Wolfenstein

9

El kitabını buradan okuyarak: http://curl.haxx.se/libcurl/c/curl_easy_setopt.html CURL_SETOPT için birkaç çağrıya ihtiyacınız olduğunu düşünüyorum, ilki işlemek istediğiniz URL, ikincisi ise şuna benzer:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function_ptr);

Function_ptr bu imzayla eşleştiğinde:

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

Burada olan şey, libcurl'un çağırdığınız aktarımdan yazmak için bir çıktıya sahip olduğunda çağıracağı bir geri arama işlevini belirtmenizdir. Otomatik olarak bir dosyaya yazmasını sağlayabilir veya çıktının kendisini işleyecek bir işleve bir işaretçi iletebilirsiniz. Bu işlevi kullanarak çeşitli çıktı dizilerini tek parça halinde bir araya getirebilmeli ve ardından bunları programınızda kullanabilmelisiniz.

Başka hangi seçenekleri belirlemeniz gerekebileceğinden / uygulamanızın nasıl davranmasını istediğinizi başka neler etkileyebileceğinden emin değilim, bu nedenle o sayfaya iyice bakın.


2

İşte alex-jasmin'den kabul edilen cevabın bir C ++ çeşidi

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.