c++clibcurl

libcurl output to variable instead of textfile


In failing to get curlpp for C++ working, I have decided to start using libcurl with C instead (for now). Being completely new to both C and C++, this is getting a little confusing. I'm not even sure if I can keep C and C++ functions apart, but as far as I know, this is pure C.

With the help of a friend, I have managed to write the output (page contents that curl picked up) to a textfile, but I want to put it in a string variable instead, so I can use the output in other parts of the code. I could just re-open the textfile and read its contents but that's silly, I want to stop writing to a file and just save to a string variable immediately.

The write function

/* the function to invoke as the data received */
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    size_t written;
    written = fwrite(ptr, size, nmemb, stream);
    return written;
}

The entire code

#include <iostream>
#include "curl/curl.h"

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

#include <iostream>
using namespace std;

/* the function to invoke as the data recieved */
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    size_t written;
    written = fwrite(ptr, size, nmemb, stream);
    return written;
}

int main(int argc, char *argv[]) {

    CURL *curl;
    FILE *fp;
  CURLcode res;

  curl = curl_easy_init();

char outfilename[FILENAME_MAX] = "C:\\Users\\admin\\Downloads\\bbb.txt";

  if(curl) {
char *response = NULL;

        fp = fopen(outfilename,"wb");
        curl_easy_setopt(curl, CURLOPT_URL, "http://www.*hidden*.org/wp-test/lalala.txt");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        res = curl_easy_perform(curl);

        curl_easy_cleanup(curl);
        fclose(fp);


  }
    return 0;
}

I was also hoping someone could elaborate on how this function is used, exactly. I am used (from php and vb.net) to a function like this:

function1(ThisIsAvariable,ThisIsAvariableToo)
{
    if ThisIsAvariable = something
    {
         Print "gogopowerrrangers" *append* ThisIsAvariableToo
    }
};

Which would then be used like:

function1(PassThisAsVariable1,PassThisAsVariable2);

But in the code above, the function

size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)

Is simply called like this

write_data

As you can see here:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);

So what's all this for?

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

Does curl automatically "fill" those in or does C/C++ work differently with functions than most other languages?


Solution

  • You could use a string stream to save the data in memory. You would create the string stream in main and pass a pointer to it to curl, like you currently pass a pointer to a FILE.

    #include <sstream> // required for std::ostringstream
    // ...
    
    std::ostringstream stream;
    
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream);
    
    // call curl like before
    // ...
    
    // then get result as a std::string:
    std::string output = stream.str();
    

    The according write_data function would look like this:

    size_t write_data(char *ptr, size_t size, size_t nmemb, void *userdata) {
        std::ostringstream *stream = (std::ostringstream*)userdata;
        size_t count = size * nmemb;
        stream->write(ptr, count);
        return count;
    }
    

    And about the function calling, it works basically the same way as in other languages. You have to give parameters to the function if you call it. The difference in this case is, that in curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data) the write_data function isn't called. write_data is instead given as a parameter to curl_easy_setopt which informs curl that is should use this function when it needs to write data.

    Later then, once curl receives data and wants to write that data, it will call write_data with all the appropriate parameters.