Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Problema con libreria curl
Forum - C/C++ - Problema con libreria curl

Avatar
a_butta (Member)
Expert


Messaggi: 578
Iscritto: 16/03/2010

Segnala al moderatore
Postato alle 10:26
Sabato, 29/10/2016
Ciao a tutti.
Anche se con gran fatica, son riuscito alla fine ad installare la libreria cURL attraverso MSYS64.
cURL, di per sé, funziona: se lo avvio da linea di comando e testo l'acquisizione del sito www.google.com ricevo la pagina HTML.
Ora il problema è implementarlo nel mio programma (C++): uso eclipse (compilatore MinGW) e sto cercando di testare un semplicissimo GET. Per il collegamento con il compilatore ho seguito e istruzioni sul web e sfruttato il comando curl-config:

Codice sorgente - presumibilmente Plain Text

  1. curl-config --cflags
  2. -I/usr/local/include
  3.  
  4. curl-config --libs
  5. -L/usr/local/lib -lcurl -lwldap32 -lz -lws2_32



Sono andato sotto le opzioni Build->Settings:
In GCC C++ Compiler->Includes e GCC C Compiler->Includes ho aggiunto il primo collegamento (ho usato un path assoluto: C:/msys64/usr/local/include). Sotto l'opzione MinGW C++ Linker->Miscellaneous, nel Linker flags ho copiato la risposta al secondo comando (sempre con path assoluto: -LC:/msys64/usr/local/lib -lcurl -lwldap32 -lz -lws2_32.

Sono dunque andato a prendere il file di esempio più semplice, trovato nel pacchetto curl:

Codice sorgente - presumibilmente C/C++

  1. int main()
  2. {
  3.           CURL *curl;
  4.           CURLcode res;
  5.  
  6.           curl = curl_easy_init();
  7.           if(curl) {
  8.             curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com/");
  9.             res = curl_easy_perform(curl);
  10.  
  11.             if(CURLE_OK == res) {
  12.               char *ct;
  13.               /* ask for the content-type */
  14.               res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
  15.  
  16.               if((CURLE_OK == res) && ct)
  17.                 cout << std::string(ct);
  18.             }
  19.  
  20.             /* always cleanup */
  21.             curl_easy_cleanup(curl);
  22.           }
  23.  
  24.     return 0;
  25. }



Ho modificato soltanto la stampa a video sostituendo ad uno fprintf il std::cout con conversione da char* a std::string.

Fatto il Build nessun tipo di errore: Tutto ok

Avvio il programma: termina l'avvio ed esce con exit value:-1.073.741. Cioé, non mi da ALCUN TIPO DI ERRORE ma non esegue il pezzo di codice per intero (per intenderci non arriva al return 0 del main).
Stessa identica cosa in modalità Debug: non riesco ad effettuarlo perchè il programma esce prima che possa interrompersi nel main (sembra quasi che non riesca proprio ad entrarci).

Sono alquanto incredulo... Qualche suggerimento?

Ringrazio anticipatamente

Ultima modifica effettuata da a_butta il 29/10/2016 alle 10:34
PM Quote
Avatar
a_butta (Member)
Expert


Messaggi: 578
Iscritto: 16/03/2010

Segnala al moderatore
Postato alle 15:56
Sabato, 29/10/2016
Sono riuscito a capire qualcosa in più.

Ho notato che il problema è a monte di tutto nell'inizializzazione curl_easy_init(curl). Infatti, apponendo un return 1; prima di questo, l'applicazione termina correttamente.

Andando ad avviare il programma direttamente da linea di comando (cmd) ottengo l'errore Libreria libcurl-4.dll non trovata. Dunque sono andato a porre il link a tale libreria nella variabile PATH dell' ambiente windows. Risultato: da linea di comando il programma funziona!

Ritorno su Eclipse: stesso problema. L'applicazione esce con valore diverso da zero e non funziona come prima...

Qualche suggerimento?

PM Quote
Avatar
GN (Member)
Guru


Messaggi: 772
Iscritto: 30/04/2011

Segnala al moderatore
Postato alle 16:10
Sabato, 29/10/2016
Penso che le possibili soluzioni siano 2:
- copiare la dll nella cartella dell'eseguibile e distribuirla insieme ad esso (probabilmente c'è un modo per farlo fare automaticamente ad Eclipse, ma non ne sono al corrente), comunque puoi prvare a mano.
- linkare staticamente invece che dinamicamente, in modo che tutto il necessario finisca dentro all'eseguibile; in tal caso dovresti  trovare la versione statica di quella libreria (se non sbaglio su Windows l'estensione dovrebbe essere .lib, oppure .a come su Linux) ed inserire il suo percorso nella riga di comando del linker, es. "C:/msys64/usr/local/lib/libcurl-4.lib" al posto di " -LC:/msys64/usr/local/lib -lcurl".

Inoltre avendo la libreria curl altre dipendenze ("-lwldap32 -lz", ws2 se non sbaglio non dovrebbe essere un problema perchè essendo la Winsock è già presente in Windows) probabilmente bisognerà ripetere l'operazione anche per queste 2.

Ultima modifica effettuata da GN il 29/10/2016 alle 16:11
PM Quote
Avatar
a_butta (Member)
Expert


Messaggi: 578
Iscritto: 16/03/2010

Segnala al moderatore
Postato alle 16:22
Sabato, 29/10/2016
Testo quotato

Postato originariamente da GN:
- copiare la dll nella cartella dell'eseguibile e distribuirla insieme ad esso (probabilmente c'è un modo per farlo fare automaticamente ad Eclipse, ma non ne sono al corrente), comunque puoi prvare a mano.



Sulla prima possibilità hai fatti bingo! E già per questo ti ringrazio tanto!
Scusami però devo farti una domanda da ignorante. Se dovessi compilare il mio codice su Linux, come dovrei fare? In questo modo non funzionerebbe, erro?

Testo quotato

Postato originariamente da GN:
- linkare staticamente invece che dinamicamente, in modo che tutto il necessario finisca dentro all'eseguibile; in tal caso dovresti  trovare la versione statica di quella libreria (se non sbaglio su Windows l'estensione dovrebbe essere .lib, oppure .a come su Linux) ed inserire il suo percorso nella riga di comando del linker, es. "C:/msys64/usr/local/lib/libcurl-4.lib" al posto di " -LC:/msys64/usr/local/lib -lcurl".



Nel frattempo provo a vedere col secondo metodo. Nella cartella lib ho quattro file "allettanti":
-) libcurl.a
-) libcurl.dll
-) libcurl.dll.a
-) libcurl.la
Quale dovrei collegare nel linker? Inoltre secondo il tuo esempio dovrei apporre C:/msys64/usr/local/lib/libcurl.a. In questo modo non funziona... La mancanza del tag prima del collegamento è necessaria? (intendo -l per la libreria o -L per la cartella)

PM Quote
Avatar
GN (Member)
Guru


Messaggi: 772
Iscritto: 30/04/2011

Segnala al moderatore
Postato alle 21:24
Sabato, 29/10/2016
Su linux stessa cosa, puoi linkare staticamente o dinamicamente. Di solito non si distribuiscono le librerie dinamiche (.so) insieme agli eseguibili ma si lascia risolvere la dipendenza dal package manager della distribuzione. In teoria comunque si può fare, tenendo conto che di default le librerie dinamiche non vengono cercate nella cartella di lavoro ma solo nei percorsi di sistema (es. /usr/lib, /usr/local/lib), quindi prima di avviare il programma bisogna settare la variabile d'ambiente LD_LIBRARY_PATH=. per fare in modo che vengano cercati i .so nella cartella di lavoro.
Che io sappia comunque è un metodo sconsigliabile, di solito si distribuiscono i pacchetti per le varie distribuzioni (.deb, .rpm, ecc) contenenti solo il programma vero e proprio e/o un .tar.gz con i sorgenti e la documentazione per compilare. Quando si genera il pacchetto si specificano le dipendenze necessarie e sarà il package manager a risolverle al momento dell'installazione sul computer dell'utente.
Sto andando leggermente OT, comunque consiglio questo tool per costruire pacchetti per varie distribuzioni: https://github.com/jordansissel/fpm, è abbastanza ben documentato ed è molto comodo perchè consente di generare pacchetti in vari formati con un solo comando.

Per la questione del linking statico che errore ottieni? L'avevo fatto tempo fa ma non ricordo bene, dovrebbe essere spiegato nella documentazione di curl. Mi viene in mente ora che bisogna anche specificare -DCURL_STATIC_LIB al compilatore.

PM Quote