用于现代C ++的libcurl和JSON问题

时间:2018-09-24 20:30:38

标签: c++ json libcurl

我正在尝试通过编写一个简单的程序来自学C ++,该程序将cURL请求发送到JSON API,解析数据,然后将其存储在文本文档或数据库中,以供Web应用程序访问。我已经在PHP中完成了此任务,并认为C ++不会困难得多,但我什至无法获得cURL返回字符串并显示它。

我将其编译为没有错误,但是响应"JSON data: "在JSON数据应显示的位置未显示任何内容。

我哪里出错了? URL-to-API是实际的URL,所以我认为我使用了错误的setopt函数,或者未设置任何函数。在PHP中,"CURLOPT_RETURNTRANSFER"使其以字符串形式返回,但出现错误:

  

错误:未在此范围内声明“ CURLOPT_RETURNTRANSFER”
  curl_easy_setopt(curl,CURLOPT_RETURNTRANSFER,true);

我在Ubuntu上使用g ++编译器,并在命令行参数中添加了-lcurl

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <curl/curl.h>
//#include "json.hpp"

using namespace std;
//using json = nlohmann::json;

size_t WriteCallback(char *contents, size_t size, size_t nmemb, void *userp) {
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

string getJSON(string URL) {

    CURL *curl;
    CURLcode res;
    string readBuffer;

    curl = curl_easy_init();
    if(curl) {

        curl_easy_setopt(curl, CURLOPT_HEADER, 1);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); // follow redirect
        //curl_easy_setopt(curl, CURLOPT_RETURNTRANSFER, true); // return as string
        curl_easy_setopt(curl, CURLOPT_HEADER, false);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_URL, URL);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);     

        res = curl_easy_perform(curl);

    /* always cleanup */
        curl_easy_cleanup(curl);

        return readBuffer;
    }

    return 0;
}

int main() {

    string data = getJSON("URL-to-api");

    cout << "JSON Data: \n" << data;

    return 0;
}

当我取消对Modern C ++包含和名称空间行的JSON的注释时,出现此错误:

  

错误此文件需要ISO C ++ 2011标准的编译器和库支持。必须使用-std = c ++ 11或-std = gnu ++ 11编译器选项启用此支持。

该库中的函数伴随着许多错误。在开始这个项目之前,我只是下载了最新版本的g ++,那么我该怎么办?

我正在Ubuntu上使用g ++ 5.4.0。

更新:

因此,我在res = curl_easy_perform(curl)下添加了一条支票,它没有返回错误消息,并且res被显示为6。这似乎比应做的要困难得多。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <curl/curl.h>
//#include "json.hpp"

using namespace std;
//using json = nlohmann::json;

size_t WriteCallback(char *contents, size_t size, size_t nmemb, void *userp) {
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

string getJSON(string URL) {

    CURL *curl;
    CURLcode res;
    string readBuffer;

    curl = curl_easy_init();

    if(curl) {

        curl_easy_setopt(curl, CURLOPT_HEADER, 1);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); // follow redirect
        curl_easy_setopt(curl, CURLOPT_HEADER, false);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_URL, URL);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);     

        res = curl_easy_perform(curl);
        cout << res << endl;
        if (!res) {
            cout << "cURL didn't work\n";
        }

    /* always cleanup */
        curl_easy_cleanup(curl);
        curl = NULL;
        return readBuffer;
    }
}

int main() {

    string data = getData("");

    cout << "JSON Data: \n" << data;

    return 0;
}

运行程序时,我得到以下输出:

6
JSON Data:

1 个答案:

答案 0 :(得分:1)

  

在PHP中,“ CURLOPT_RETURNTRANSFER”使它作为字符串返回,但出现错误:

     

错误:未在此范围内声明“ CURLOPT_RETURNTRANSFER”
  curl_easy_setopt(curl,CURLOPT_RETURNTRANSFER,true);

没有为curl_easy_setopt()记录的CURLOPT_RETURNTRANSFER选项。我认为这是为PHP的curl_exec()函数指定的一个选项,CURL本身不存在此函数。 CURLOPT_WRITEFUNCTION是在这种情况下的正确方法。

  

当我取消注释现代C ++的JSON包含和命名空间行时,我得到:

     

错误此文件需要ISO C ++ 2011标准的编译器和库支持。必须使用-std = c ++ 11或-std = gnu ++ 11编译器选项启用此支持。

该错误是不言自明的。您的JSON库需要C ++ 11,但是您未在启用C ++ 11的情况下进行编译。一些现代的编译器仍默认使用较旧的C ++版本(通常是 C ++ 98),并要求您在命令行或您的命令行中调用编译器时显式启用C ++ 11(或更高版本)。项目makefile配置。

对于g ++,如果未通过-std参数另外指定,则当前版本(8.2)默认为C的C17(GNU方言)和C ++的默认C ++ 14。您的版本(5.4)分别默认为C11和C ++ 98(的GNU方言)。

更新:您的代码中还有其他错误:

  1. 您正在将std::string对象传递到curl_easy_setopt(),其中char*应该使用CURLOPT_URL指针。您需要更改此内容:

    curl_easy_setopt(curl, CURLOPT_URL, URL);
    

    为此:

    curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
    
  2. 您没有正确测试curl_easy_perform()的返回值。根据文档,curl_easy_perform()成功返回0(CURLE_OK),错误返回非零,因此您需要更改此值:

    if (!res)
    

    为此:

    if (res != CURLE_OK)
    
  3.   

    因此我在res = curl_easy_perform(curl) ...下添加了一个支票,并且res显示为6

    CURLE_COULDNT_RESOLVE_HOST,这很有意义,因为您更新的示例将空白URL传递给getJSON()

    string data = getJSON(""); // should be "URL-to-api" instead!