JosephP91 / curlcpp

An object oriented C++ wrapper for CURL (libcurl)
https://josephp91.github.io/curlcpp
MIT License
628 stars 173 forks source link

get_info(CURLINFO_COOKIELIST) not referenced #43

Closed tucanus closed 9 years ago

tucanus commented 9 years ago

Before all, thank you for your work, very useful. I built your library on Ubuntu 14.04, using libcurl 7.35 (after removing line 276 of curl_easy.h, because it caused compiling error). Then I moved header files in /usr/include/curlcpp, libcurlcpp.a in /usr/lib.

Source code of the simple test program is

#include <curlcpp/curl_easy.h>
using curl::curl_easy;

int main(int argc, const char **argv) {
    curl_easy easy;
    easy.add(curl_pair<CURLoption,string>(CURLOPT_URL,"http://www.google.it") );
    easy.add(curl_pair<CURLoption,long>(CURLOPT_FOLLOWLOCATION,1L));
    easy.add(curl_pair<CURLoption,string>(CURLOPT_COOKIEFILE,""));
    try {
        easy.perform();
        auto pippo = easy.get_info(CURLINFO_COOKIELIST);
        for(auto item : *pippo)
        {
            std::cout << item << ", " << std::endl;
        }
        std::cout << std::endl;
    } catch (curl_easy_exception &error) {
        // If you want to get the entire error stack we can do:
        std::vector<std::pair<std::string,std::string>> errors = error.get_traceback();
        // Otherwise we could print the stack like this:
        error.print_traceback();
        // Note that the printing the stack will erase it
    }
    std::cin.get();
    return 0;
}

I compiled succesfully (g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"), but linking (g++ -o "testCurlCpp" ./main.o -lcurl -lcurlcpp) fails saying

main.cpp:15: undefined reference to "curl::curl_easy::get_info(CURLINFO) const". Removing line 15 all works fine. Thank you.

JosephP91 commented 9 years ago

@tucanus Hi and thank you for using curlcpp! Try to change this line:

auto pippo = easy.get_info(CURLINFO_COOKIELIST);

with this:

auto pippo = easy.get_info<vector<string>>(CURLINFO_COOKIELIST);

get_info is a template method in which you have to specify the type. Let me know!

tucanus commented 9 years ago

Sorry, it is true, my mistake. Ok, now it compiles, but does not work, get_info throws an exception and error.print_traceback() shows ERROR: A libcurl function was given a bad argument ::::: FUNCTION: get_info<std::vector<std::basic_string<char> > >

I suspect code of get_info being incorrect (curl_easy_getinfo third parameter shoul be struct curl_slist **, you should check ptr != nullptr before applying ->next field, and should not infer that struct curl_slist elements being of same dimensions, hence I suggest to correct get_info this way (it works on my PC ;)

// Putting the namespace here will avoid the "specialization in different namespace" error.
namespace curl {
    template<> std::unique_ptr<std::vector<std::string>> curl_easy::get_info(const CURLINFO info) const {
        struct curl_slist *ptr = nullptr;
        const CURLcode code = curl_easy_getinfo(this->curl,info,&ptr);
        if (code != CURLE_OK) {
            curl_slist_free_all(ptr);
            throw curl_easy_exception(code,__FUNCTION__);
        }
        std::vector<std::string> infos;

        struct curl_slist *list = ptr;
        while (list != nullptr) {
            infos.push_back(std::string(list->data));
            list = list->next;
        }
        curl_slist_free_all(ptr);
        return std::unique_ptr<std::vector<std::string>>{new std::vector<std::string>(infos)};
    }
}

Thank you for your support and your time.

JosephP91 commented 9 years ago

@tucanus Yeah, right! Now it works also on my environment! Thank you! If everything works, you can close the issue. For anything else, let me know! I will update the repo as soon as possible.