Thread: cURL class

  1. #1
    Registered User
    Join Date
    Aug 2007
    Posts
    85

    cURL class

    I'm building a worker class that should download stuff, via cURL.

    however, cURL has some oddities in it (using my functions to buffer and send progress, etc) and i'm far from understanding classes and pointers right.

    Basically, one of the options requires access to one of my functions (pointer), and it passes it what it downloaded. I'll have to do the rest, like writing it to a file, displaying or processing the data.

    It works fine as a 'standard' program, but I have no idea how i should make cURL access a class function. I've tried a few workarounds, but my program crashed everytime.

    Basically,
    Code:
    class pw
    {
        public:
    
        int state;
        string target;
        string file;
        string contents;
        int progress;
        pw();
    
        private:
    
        CURL *curl;
        CURLcode result;
    
        int gauge;
        string buffer;
        char errorBuffer[CURL_ERROR_SIZE];
    
        //functions
        int progressUpdater(int* gauge, double dltotal, double dlnow, double ultotal, double ulnow);
        int writer(char *data, size_t size, size_t nmemb, std::string *buffer);
    };
    ..and somewhere in the constructor:

    Code:
              curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writer);
    I need the last parameter to point individual instance function "writer".
    I've tried:
    &pw::writer
    this->writer
    &writer
    this->writer

    None works. How can I do it?

  2. #2
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    I was having similar problems before when I was pointing it to a member function. I'm not certain but now that I think about it if you make it static it might work. Alternatively just have the function outside the class like I did.

    Also, I believe that the prototyle for writer has parameters: void*, size_t, size_t and void* ... it might have problems with explicitly pointing it to a char* and std::string. Not certain about that though. If it does you can just typecast and such, but
    curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, function_name ) should work ...

  3. #3
    Registered User
    Join Date
    Aug 2007
    Posts
    85
    Hmm, that seems to work. However, now I can't get curl to execute. whenever i run curl_easy_perform, the program crashes.

    And I can't declare the CURL object anything else but a pointer in the class :/ damn, this is weird and i stopped understanding why i'm doing any corrections.

    Code:
        int pw::exec()
        {
            // Set URL
    
            curl_easy_setopt(pw::curl, CURLOPT_URL, &pw::target);
            std::cout << "1\n"; //code crashes after this point
            // Attempt to retrieve the remote page
            CURLcode temp;
            temp = curl_easy_perform(pw::curl); // i believe it crashes here. I can't seem to access the curl object anyhow.
            std::cout << "2\n";  //code crashes before this point
            // Always cleanup
            curl_easy_cleanup(pw::curl);
            std::cout << "3\n";
            // Did we succeed?
            if (pw::result == CURLE_OK)
            {
                std::cout << buffer;
            }
            else
            {
                std::cout << "Error: [" << result << "] - " << errorBuffer;
            }
        }
    Last edited by _izua_; 10-13-2007 at 05:49 AM. Reason: added source

  4. #4
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    Right. Well take out all the pw::'s. They aren't necessary. You have CURLcode already. Just assign the of curl_easy_perform to result.

    Code:
        int pw::exec()
        {
            // Set URL
    
            curl_easy_setopt(curl, CURLOPT_URL, &target);
            std::cout << "1\n"; //code crashes after this point
    
            // Attempt to retrieve the remote page
            result = curl_easy_perform(curl); // i believe it crashes here. I can't seem to access the curl object anyhow.
            std::cout << "2\n";  //code crashes before this point
    
            // Did we succeed?
            if (result == CURLE_OK)
            {
                std::cout << buffer;
            }
            else
            {
                std::cout << "Error: [" << result << "] - " << errorBuffer;
            }
        }
    Also, you should cleanup in the destrutor.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well you need to get a 'this' pointer from somewhere, since cURL knows nothing about C++.

    Code:
    #include <iostream>
    #include <string>
    
    class foo {
        std::string me;
      public:
        foo ( std::string ident ) : me(ident) { }
        static void wrapper ( void *thisptr ) { /* must be static, to stop implicit 'this' param */
          foo *instance = static_cast<foo*>(thisptr);
          instance->func();
        }
        void func ( void ) {
            std::cout << "WooHoo " << me << std::endl;
        }
    };
    
    
    static void *curlinst;
    void curlSetInst ( void *p ) {
        curlinst = p;
    }
    void curlcb ( void ) {
        /* Invoke the static class member function */
        /* Use the saved 'this' pointer as the parameter */
        /* to allow the wrapper to invoke the actual member function */
        /* with the correct this pointer. */
        foo::wrapper( curlinst );
    }
    
    
    int main ( ) {
        foo var("howdy");
        curlSetInst( &var );    /* see CURLOPT_WRITEDATA */
        curlcb();
        return 0;
    }
    > int writer(char *data, size_t size, size_t nmemb, std::string *buffer);
    Nope, the last param will be a void*, not a std::string.
    Use the above to make data represent your 'this' function, from which you'll be able to get the rest of your class data.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Aug 2007
    Posts
    85
    is there an easier way to get around this? I've been experimenting with the above class for several hours and i haven't really understood anything. my c skills suck.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well you're trying to mix C and C++, and calling C++ code from C takes some doing.
    Post more of your latest code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Aug 2007
    Posts
    85
    I haven't made any new code on my project, I've been trying to understand yours But it's too complex for me, i guess.
    Is there an easy to use C++ curl wrapper? I've found curlpp, but it's too complex.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Generally, making object oriented interfaces for some complex functionality (curl isn't trivial, at least) makes for complex interface classes. It may be possible to hide a lot of the funcitonality behind the scenes if the functionality you need is restricted to a small subset of the library you are interfacing to, but you can't just hide all that functionality completely and still expect it to automatically know what you want to do and how.

    The callback functionality you are after is a common scenario for Windows C++ programming (since the Windows API makes use of callbacks for plenty of things), and the solution is to make a static wrapper that gets the class pointer from a void pointer, like Salem shows.

    If you want C to understand classes, you need C++, and libraries or APIs that aren't written in/for C++ won't do that...

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    There is the curlpp project ... http://curl.haxx.se/libcurl/cplusplus/ I've never used it now so I don't know how it works or if it's any good ... As far as I know it's just wrapping code but it should work ...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Class design problem
    By h3ro in forum C++ Programming
    Replies: 10
    Last Post: 12-19-2008, 09:10 AM
  2. Specializing class
    By Elysia in forum C++ Programming
    Replies: 6
    Last Post: 09-28-2008, 04:30 AM
  3. Defining derivated class problem
    By mikahell in forum C++ Programming
    Replies: 9
    Last Post: 08-22-2007, 02:46 PM
  4. matrix class
    By shuo in forum C++ Programming
    Replies: 2
    Last Post: 07-13-2007, 01:03 AM