YAMAGUCHI::weblog

土足で窓から失礼いたします。今日からあなたの息子になります。 当年とって92歳、下町の発明王、エジソンです。

libcurlでHTTPレスポンスの結果をchar*に保存する

はじめに

こんにちは、Python界のSIGSEGVです。C/API拡張書こうと思って色々書き散らかしてるわけですが、libcurl使って結果をchar*に保存する方法にけっこう時間を取られたのでメモします。

参考

本家のサンプルコード見れば大体わかると思いますが、なにせAPIが多いので慣れるまではググってピンポイントで使いどころ調べるほうが速い。読み込んだものを直接標準出力に吐く場合は特に気にすることないんですが、char*に保存したい場合は、callback関数を書いてやって、curl_easy_setoptにCURLOPT_WRITEFUNCITONとCURLOPT_WRITEDATAの2つのオプションをセットしてやる。

コード

適当に動いてるコードから抜粋してきたのでこのままじゃ動かないけど、雰囲気だけ。

#include <curl/curl.h>

typedef struct
{
    char* memory;
    size_t size;
} Memory;

size_t
write_memory_callback(void* ptr, size_t size, size_t nmemb, void* data)
{
    if (size * nmemb == 0)
        return 0;

    size_t realsize = size * nmemb;
    Memory* mem = (Memory*)data;
    
    mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1);
    if (mem->memory) {
        memcpy(&(mem->memory[mem->size]), ptr, realsize);
        mem->size += realsize;
        mem->memory[mem->size] = 0;
    }

    return realsize;
}

int
get_content(Memory* mem, char* url)
{
    CURL* curl;
    CURLcode res;
    
    curl = curl_easy_init();

    if (!curl)
        return 1;

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)mem);

    res = curl_easy_perform(curl);
    if (res)
        return 1;
    curl_easy_cleanup(curl);
    
    return 0;
}

int
main()
{
    Memory* mem = malloc(sizeof(Memory*));
    int res;

    mem->size = 0;
    mem->memory = NULL;

    res = get_content(mem, "http://example.com/");
    if (res)
        return 1;

    // do something on mem

    free(mem->memory);
    free(mem);

    return 0;
}