1

c++ / curl here on stackoverflow に関するいくつかの記事を読み、以下を組み立てました。主な目標は、クラスのインスタンスでリクエスト全体を処理することです。おそらく後でセカンダリ スレッドで処理します。

私の問題は次のとおりです。「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; 
}

main.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インスタンスを作成し、それを別のインスタンスにコピーします。したがって、2つのインスタンスと2つのコンテンツ文字列があります。この問題を削除するには、次のように変更します。

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

別のエラーは行です

curl_easy_setopt(curl, CURLOPT_URL, &url);

これは

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

HttpFetchのようなクラスでのリソース管理について考えていれば、このような問題を回避できたはずです。HttpFetchはリソース(カールハンドル)を管理するため、このリソースを初期化およびクリーンアップする方法、コピー、割り当て、または移動を処理する方法を検討する必要があります。C ++ 11を使用する場合、最も簡単な解決策は、std::unique_ptrすべてのものを処理するを使用することです。

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 に答える