Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Curlpp przypisywanie wyniku do zmiennej

Ostatnio zmodyfikowano 2017-09-20 23:19
Autor Wiadomość
Bastian
Temat założony przez niniejszego użytkownika
Curlpp przypisywanie wyniku do zmiennej
» 2017-08-27 09:58:12

Czesc,

Pisze oto taką metode, która ma być parserem HTTP/HTTPS

C/C++
void KGrawler::parser( char * url )
{
   
    using namespace curlpp::options;
   
    try
    {
        // That's all that is needed to do cleanup of used resources (RAII style).
        curlpp::Cleanup myCleanup;
       
        // Our request to be sent.
        curlpp::Easy myRequest;
       
        // Set the URL.
        //myRequest.setOpt(curlpp::Options::Url(url));
        myRequest.setOpt < Url >( url );
       
        // Send request and get a result.
        // By default the result goes to standard output.
        myRequest.perform();
    }
    catch( curlpp::RuntimeError & e )
    {
        std::cout << e.what() << std::endl;
    }
   
    catch( curlpp::LogicError & e )
    {
        std::cout << e.what() << std::endl;
    }
}

W domyslnych ustawieniach curlpp::Easy:perform() wyrzyguje output na stdout. Aby zmienic do zachowanie z tego co czytam należy ustawić odpowiednio curlpp::OptionTrait<void *, CURLOPT_WRITEDATA>

Zatem probuje w taki sposób:

C/C++
void KGrawler::parser( char * url )
{
   
    using namespace curlpp::options;
   
    try
    {
        // That's all that is needed to do cleanup of used resources (RAII style).
        curlpp::Cleanup myCleanup;
       
        // Our request to be sent.
        curlpp::Easy myRequest;
       
        // Set the URL.
        //myRequest.setOpt(curlpp::Options::Url(url));
       
        //Redirect output to std::string object instead default std::cout             
        std::string oput;
        curlpp::OptionTrait < void *, CURLOPT_WRITEDATA > myData( oput );
        request.setOpt( myData );
       
        // Send request and get a result.
        // By default the result goes to standard output.
        myRequest.perform();
    }
    catch( curlpp::RuntimeError & e )
    {
        std::cout << e.what() << std::endl;
    }
   
    catch( curlpp::LogicError & e )
    {
        std::cout << e.what() << std::endl;
    }
}

Niestety słabo to rozumiem i dostaje błąd kompilacji:


/home/grzempek/git/KGrawler/src/KGrawler.cpp|66|error: no matching function for call to ‘curlpp::OptionTrait<void*, (CURLoption)10001u>::OptionTrait(std::string&)’|

Ktoś wie jak to poprawnie zrobić?

pzdr
P-164314
j23
» 2017-08-27 10:45:31
Przecież z treści błędu jasno wynika, że podajesz argument o niewłaściwym typie. Jakoś tak powinno być:

curlpp::WriteData myData( static_cast < void *>( & oput ) );
P-164318
Bastian
Temat założony przez niniejszego użytkownika
» 2017-09-07 21:02:52
Hej,

Program sie skompilował ale oczywiście nie działa poprawnie.

Rozumiem, że na podstawie błędu wywioskowałeś, że powinienem zrobić tak:
C/C++
curlpp::OptionTrait < void *, CURLOPT_WRITEDATA > myData( static_cast < void *>( & oo ) );

Jeśli dobrze to czytam to jest to instancja klasy szablonowej curlpp::OptionTrait z argumentami szablonu w postaci wskaznika (void *) oraz stałej CURLOPT_DATA. Instancja klasy o nazwie myData() przyjmuje argumenty o takim typie jaki podaje w szablonie a więc void *, ale z racji tego ze chce przekazać std::string oo to trzeba użyć rzutowania czyli static_cast<void *>(& oo))

Prosze o potwierdzenie, że dobrze to rozumiem, bo ta składnia i sygnatury w C++ doprowadzają mnie do szaleństwa :)

Druga sprawa jest taka, że program działa niepoprawnie

Dostaje przy próbie zapisania


Failed writing body (0 != 665)

Zgodnie z przykładem:

https://github.com/jpbarrette​/curlpp/blob/master/examples​/example11.cpp

...trzeba stworzyc callback i przekazac go do klasy
C/C++
curlpp::options::WriteFunctionCurlFunction

..tyle ze tam jest zapis outputu do pliku a ja chce zapisać w zmiennej do dalszej analizy.

Jak widzicie dopiero raczkuje i potrzebna mi pomoc...
P-164700
j23
» 2017-09-08 12:02:26
Prosze o potwierdzenie
Dobrze to rozumiesz. Użyłem curlpp::WriteData, żeby uprościć zapis.

Druga sprawa jest taka, że program działa niepoprawnie
Callback jakoś tak powinien wyglądać:
C/C++
size_t write_to_string_callback( char * ptr, size_t size, size_t nmemb, void * pstr )
{
    std::string * s = static_cast < std::string *>( pstr );
   
    size *= nmemb;
    s->append( ptr, size );
    return size;
};
P-164722
Bastian
Temat założony przez niniejszego użytkownika
» 2017-09-14 21:05:21
Zrobilem tak:


C/C++
size_t KGrawler::WriteToStringCallback( char * ptr, size_t size, size_t nmemb, void * pstr )
{
    std::string * s = static_cast < std::string *>( pstr );
    size *= nmemb;
    s->append( ptr, size );
    return size;
}

void KGrawler::parser( char * url )
{
    std::cout << std::endl << std::endl;
    std::cout << url << std::endl;
    using namespace curlpp::options;
   
    try
    {
        // That's all that is needed to do cleanup of used resources (RAII style).
        curlpp::Cleanup myCleanup;
       
        // Our request to be sent.
        curlpp::Easy myRequest;
       
        // Set the writer callback to enable cURL to write result in a memory area
        WriteFunctionCurlFunction myFunction( WriteToStringCallback );
        std::string oo;
        curlpp::OptionTrait < void *, CURLOPT_WRITEDATA > myData( static_cast < void *>( & oo ) );
       
        myRequest.setOpt( myFunction );
        myRequest.setOpt( myData );
       
        // Set the URL.
        //myRequest.setOpt(curlpp::Options::Url(url));
        myRequest.setOpt < Url >( url );
       
        // Send request and get a result.
        // By default the result goes to standard output.
        myRequest.perform();
    }
    catch( curlpp::RuntimeError & e )
    {
        std::cout << e.what() << std::endl;
    }
   
    catch( curlpp::LogicError & e )
    {
        std::cout << e.what() << std::endl;
    }
}

Ale teraz rzyga:


In member function ‘void KGrawler::parser(char*)’:|
no matching function for call to ‘curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>::OptionTrait(<unresolved overloaded function type>)’|
 candidates are:|
curlpp::OptionTrait<OptionType, opt>::OptionTrait() [with OptionType = long unsigned int (*)(char*, long unsigned int, long unsigned int, void*); CURLoption opt = (CURLoption)20011u]|
 candidate expects 0 arguments, 1 provided|
curlpp::OptionTrait<OptionType, opt>::OptionTrait(typename curlpp::Option<OptionType>::ParamType) [with OptionType = long unsigned int (*)(char*, long unsigned int, long unsigned int, void*); CURLoption opt = (CURLoption)20011u; typename curlpp::Option<OptionType>::ParamType = long unsigned int (*)(char*, long unsigned int, long unsigned int, void*)]|
no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘curlpp::Option<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*)>::ParamType {aka long unsigned int (*)(char*, long unsigned int, long unsigned int, void*)}’|
curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>::OptionTrait(const curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>&)|
no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘const curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>&’|
curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>::OptionTrait(curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>&&)|
no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>&&’|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

Przyznam szczerze, że teraz nie rozumiem, która metode wywoluje ze zlymi atrybutami:


no matching function for call to ‘curlpp::OptionTrait<long unsigned int (*)(char*, long unsigned int, long unsigned int, void*), (CURLoption)20011u>::OptionTrait(<unresolved overloaded function type>)
P-164881
Monika90
» 2017-09-15 09:23:07
C/C++
WriteFunctionCurlFunction myFunction( WriteToStringCallback );
WriteToStringCallback to jest funkcja składowa klasy. Taką funkcję można wywołać, wtedy należy podać jej argumenty, albo pobrać jej adres, co wygląda tak
& KGrawler::WriteToStringCallback
.  Ale WriteFunctionCurlFunction pewnie nie zadziała z funkcją składową.
P-164906
j23
» 2017-09-15 10:25:44
Zrób WriteToStringCallback metodą statyczną.
P-164912
Bastian
Temat założony przez niniejszego użytkownika
» 2017-09-20 20:54:12

WriteToStringCallback to jest funkcja składowa klasy. Taką funkcję można wywołać, wtedy należy podać jej argumenty, albo pobrać jej adres, co wygląda tak & KGrawler::WriteToStringCallback
.  Ale WriteFunctionCurlFunction pewnie nie zadziała z funkcją składową

Rozumiem, że Twoim zdaniem nie można jej było zastosować jako metode klasy KGrawler?? A możesz napisać dlaczego tak uważasz? Po sugestii kolegi j23 program sie skompilował i callback działa poprawnie, ale dla dobrego zrozumienia chciałbym poznać Twoją opinie.


Zrób WriteToStringCallback metodą statyczną.

Program sie skompilowal i zdaje się ze działa poprawnie. Wybaczcie, że mam pytania, ale ucze się sam i nie mam kogo dopytywać...

C/C++
size_t KGrawler::WriteToStringCallback( char * ptr, size_t size, size_t nmemb, void * pstr )
{
    std::string * s = static_cast < std::string *>( pstr );
    size *= nmemb;
    s->append( ptr, size );
    return size;
}

size_t KGrawler::WriteToStringCallback( char * ptr, size_t size, size_t nmemb, void * pstr )
Atrybuty tego callbacka pochodzą z nagłówków samego libcurla, to znalazłem
C/C++
typedef size_t( * curl_write_callback )( char * buffer,
size_t size,
size_t nitems,
void * outstream );

std::string * s = static_cast < std::string *>( pstr );
Przypisujesz do wskaznika o typie std::string zrzutowaną na typ string wartość ze wskaźnika pstr

C/C++
size *= nmemb
Tego nie rozumiem. 'size' to wielkosc buffora danego odczytu a nmemb ? Ilosc znaków z buffora?

C/C++
s->append( ptr, size );
Appendujesz do obiektu wskaznika na obiekt s typu std::string zawartosc buffora (dany odczyt http), a paramert size jest iloscią znaków, która ma appendować.
A dlaczego nie wystarczy samo:
C/C++
s->append( ptr );
Zgodnie z dokumentacja powinno appendować całą zawartosc 'prt' no nie ?
P-165040
« 1 » 2
  Strona 1 z 2 Następna strona