1

我在 stackoverflow 上阅读了几篇关于 c++/curl 的文章并组装了以下内容。主要目标是在一个类的实例中处理整个请求——也许稍后在辅助线程中。

我的问题是:“content_”虽然地址相同,但似乎保持空白

HttpFetch.h:

class HttpFetch
{
private:
    CURL *curl;
    static size_t handle(char * data, size_t size, size_t nmemb, void * p);
    size_t handle_impl(char * data, size_t size, size_t nmemb);
public:
    std::string content_;
    static std::string url_;
    HttpFetch(std::string url);
    void start();
    std::string data();
};

HttpFetch.cpp:

HttpFetch::HttpFetch(std::string url) {

    curl_global_init(CURL_GLOBAL_ALL); //pretty obvious
    curl = curl_easy_init();

    content_.append("Test");
    std::cout << &content_ << "\n";

    curl_easy_setopt(curl, CURLOPT_URL, &url);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content_);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &HttpFetch::handle);
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //tell curl to output its progress
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

    //std::cout << &content_ << "\n";
}

void HttpFetch::start() {

    curl_easy_perform(curl);
    curl_easy_cleanup(curl);
}

size_t HttpFetch::handle(char * data, size_t size, size_t nmemb, void * p)
{
    std::string *stuff = reinterpret_cast<std::string*>(p);

    stuff->append(data, size * nmemb);

    std::cout << stuff << "\n"; // has content from data in it!

    return size * nmemb; 
}

主.cpp:

#include "HttpFetch.h"
int main(int argc, const char * argv[])
{

    HttpFetch call = *new HttpFetch("http://www.example.com");
    call.start();

    ::std::cout << call.content_ << "\n"
}

提前致谢

4

1 回答 1

1

您的代码有几个问题。主要问题是线路

HttpFetch call = *new HttpFetch("http://www.example.com");

您创建一个新的 HttpFetch 实例并将其复制到另一个实例。所以你有两个实例和两个内容字符串。要删除此问题,请将其更改为:

HttpFetch call("http://www.example.com");

另一个错误是行

curl_easy_setopt(curl, CURLOPT_URL, &url);

应该是

curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

如果您考虑过像 HttpFetch 这样的类中的资源管理,您本可以避免此类问题。由于 HttpFetch 管理一个资源(一个 curl 句柄),您必须考虑如何初始化和清理该资源以及如何处理复制、分配或移动。如果您使用 C++11,最简单的解决方案是使用std::unique_ptr为您处理所有这些东西的 a。

class HttpFetch
{
public:
    HttpFetch(const std::string& url);
    void start();
    void Print(std::ostream& stream);
private:
    typedef void (*cleanup)(CURL*);
    typedef std::unique_ptr<CURL, cleanup> CurlHandle;

    CurlHandle curlHandle;
    std::string content_;

    static size_t handle(char * data, size_t size, size_t nmemb, void * p);
};


HttpFetch::HttpFetch(const std::string& url) 
    : curlHandle(curl_easy_init(), &curl_easy_cleanup)
{
    curl_easy_setopt(curlHandle.get(), CURLOPT_URL, url.c_str());
    curl_easy_setopt(curlHandle.get(), CURLOPT_WRITEDATA, &content_);
    curl_easy_setopt(curlHandle.get(), CURLOPT_WRITEFUNCTION, &HttpFetch::handle);
    curl_easy_setopt(curlHandle.get(), CURLOPT_FOLLOWLOCATION, 1L);
}

size_t HttpFetch::handle(char * data, size_t size, size_t nmemb, void * p){
    std::string *stuff = static_cast<std::string*>(p);
    stuff->append(data, size * nmemb);
    return size * nmemb; 
}

void HttpFetch::start() {
    content_.clear();
    curl_easy_perform(curlHandle.get());
}

void HttpFetch::Print(std::ostream& stream){
    stream << content_;
}

int main()
{
    //HttpFetch call = *new HttpFetch("...");  // this is a copiler error now
    HttpFetch call("http://www.google.com");
    call.start();

    call.Print(std::cout);
}

使用unique_ptr您的类 HttpFetch 变得不可复制且只能移动。在您提供在不同 HttpFetch 实例之间复制或共享 CURL 句柄的逻辑之前,这是有意义的。

于 2012-12-02T11:02:23.293 回答