每天进步一点点:C++ 中使用libcurl 获取返回数据的学习

最近使用学习在C++中使用libcurl,不得不感概PHP是世界上最好的语言,PHP用curl那叫一个省心。Python用起来就要略复杂了,详情可以看我之前的学习笔记《每天进步一点点:Python中使用PycURL访问STEEM RPC》。不过嫌弃PycURL麻烦的可以换Requests等其它库。

但是C++使用libcurl 呢?哎,全是泪水。


(图源 :pixabay)

POST、GET

其实libcurl简单的POST、GET操作还是很简单的

可以参考以下链接:

以POST操作为例:

大致就是初始化、设置参数、执行、清理四个步骤。运行上述代码,我们也可以看到POST的返回内容。但是等等,内容是咋返回的呢?

libcurl 返回数据

默认至stdout

为了找回数据是咋返回的,我搜索了一些文档,不过还是看的迷迷糊糊的,知道我看了这两个页面:

其中CURLOPT_WRITEDATA的说明中提到:

By default, this is a FILE * to stdout.

也就是说数据默认输出到标准输出。这就解释了上述GET、POST示例中并没有使用cout、printf一类的输出操作,我们却可以看到内容。

保存至变量

接下来的问题是,如何将我们要的输出数据保存到变量呢?一种方法是CURLOPT_WRITEDATA中的文件指针换成我们自己的文件,然后输出到文件,(再读回来),如果是下载文件等操作,这种方法还是很便利的。但是如果我们需要在程序中处理数据呢?再读回来的操作显然很傻。

答案是使用CURLOPT_WRITEFUNCTION以及CURLOPT_WRITEDATA,当我们设置了CURLOPT_WRITEFUNCTION,每次我们收到数据后,这个回调函数将会被调用。

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);

其中ptr是我们收到数据的指针,数据长度为size*nmembuserdata是由CURLOPT_WRITEDATA设置的变量,操作方式如下:

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);

使用CURLOPT_WRITEFUNCTION需要注意以下几点:

  • 回调函数可能被调用不止一次,换句话将数据可能不是一次性返回的
  • 每次返回的数据长度为:size*nmemb
  • 回调函数需要返回接收数据的长度,否则会引发CURLE_WRITE_ERROR

我在这三点上都栽过跟头,希望大家注意别犯和我一样的错误。

保存到变量的例子

libcurl的例子页面,提供了一个将返回数据保存到变量的例子

Shows how the write callback function can be used to download data into a chunk of memory instead of storing it in a file.

例子中定义一个包含指向内存的指针变量,以及接受到的数据长度的变量,然后使用molloc以及realloc以及memcpy来操作内存。这样每次回调函数被调用就会自动计算需要的内存,动态分配,然后复制数据。

这个例子使用了C语言的一些手法来达成这个目的,相对而言比较复杂,需要我们自己管理以及释放内存等。对于文本数据而言,使用string还是超方便的,这里就不再赘述了。

参考链接

H2
H3
H4
3 columns
2 columns
1 column
2 Comments