-8

I have tried googling, and found no solution to my problem. I'm trying to learn how to use libcurl, a c networking library. I tried compiling a program that was automatically generated from curl, and a few examples i found online but nothing happened. I got no errors or logs, the program stopped "sucessfully" but i get no output. I also cant write to the console either while the library is included.

Any help is appreciated.

top 17 comments
sorted by: hot top controversial new old
[-] palebluethought@lemmy.world 20 points 3 weeks ago

There's no way to even attempt to answer your question without the actual code

[-] Irelephant@lemm.ee 1 points 3 weeks ago

You're right, but it doesn't do anything, no matter what the code is, so I assumed that I needn't include it. Kinda stupid of me. In any case, here it is:

/********* Sample code generated by the curl command line tool **********
 * All curl_easy_setopt() options are documented at:
 * https://curl.se/libcurl/c/curl_easy_setopt.html
 ************************************************************************/
#include <curl/curl.h>

int main(int argc, char *argv[])
{
  CURLcode ret;
  CURL *hnd;

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "https://pastebin.com/api/api_post.php");
  curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "api_dev_key=MY_API_KEY&api_paste_code=test&api_option=paste");
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)81);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/8.9.1");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may choose to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA was set to an object pointer
  CURLOPT_WRITEFUNCTION was set to a function pointer
  CURLOPT_READDATA was set to an object pointer
  CURLOPT_READFUNCTION was set to a function pointer
  CURLOPT_SEEKDATA was set to an object pointer
  CURLOPT_SEEKFUNCTION was set to a function pointer
  CURLOPT_ERRORBUFFER was set to an object pointer
  CURLOPT_STDERR was set to an object pointer
  CURLOPT_HEADERFUNCTION was set to a function pointer
  CURLOPT_HEADERDATA was set to an object pointer

  */

  ret = curl_easy_perform(hnd);

  curl_easy_cleanup(hnd);
  hnd = NULL;

  return (int)ret;
}
/**** End of sample code ****/

Another piece of code i tried was:

#include <stdio.h>
#include <curl/curl.h>

int main(void) {
    CURL *curl;
    CURLcode res;


    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if(curl) {
       
        curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:5000/a");

     
        const char *data = "hello!";
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);


        res = curl_easy_perform(curl);

     
        if(res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }

  
        curl_easy_cleanup(curl);
    }

  
    curl_global_cleanup();

    return 0;
}

compiled it with gcc test.c -o test.exe -IC:\Users\MY_USERNAME\scoop\apps\curl\current\include -LC:\Users\MY_USERNAME\scoop\apps\curl\current\lib -lcurl but you can replace the paths with wherever the libcurl include directory is (i hope).

[-] borf@lemmynsfw.com 4 points 3 weeks ago* (last edited 3 weeks ago)

I got no errors or logs, the program stopped “sucessfully” but i get no output.

This makes it sound like your code is doing what you're telling it to do with no errors. Show us your code and we can help figure out the delta between expectation and reality.

[-] Irelephant@lemm.ee 1 points 3 weeks ago

You're right, but it doesn't do anything, no matter what the code is, so I assumed that I needn't include it. Kinda stupid of me. In any case, here it is:

/********* Sample code generated by the curl command line tool **********
 * All curl_easy_setopt() options are documented at:
 * https://curl.se/libcurl/c/curl_easy_setopt.html
 ************************************************************************/
#include <curl/curl.h>

int main(int argc, char *argv[])
{
  CURLcode ret;
  CURL *hnd;

  hnd = curl_easy_init();
  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
  curl_easy_setopt(hnd, CURLOPT_URL, "https://pastebin.com/api/api_post.php");
  curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "api_dev_key=MY_API_KEY&api_paste_code=test&api_option=paste");
  curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)81);
  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/8.9.1");
  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
  curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);

  /* Here is a list of options the curl code used that cannot get generated
     as source easily. You may choose to either not use them or implement
     them yourself.

  CURLOPT_WRITEDATA was set to an object pointer
  CURLOPT_WRITEFUNCTION was set to a function pointer
  CURLOPT_READDATA was set to an object pointer
  CURLOPT_READFUNCTION was set to a function pointer
  CURLOPT_SEEKDATA was set to an object pointer
  CURLOPT_SEEKFUNCTION was set to a function pointer
  CURLOPT_ERRORBUFFER was set to an object pointer
  CURLOPT_STDERR was set to an object pointer
  CURLOPT_HEADERFUNCTION was set to a function pointer
  CURLOPT_HEADERDATA was set to an object pointer

  */

  ret = curl_easy_perform(hnd);

  curl_easy_cleanup(hnd);
  hnd = NULL;

  return (int)ret;
}
/**** End of sample code ****/

Another piece of code i tried was:

#include <stdio.h>
#include <curl/curl.h>

int main(void) {
    CURL *curl;
    CURLcode res;


    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if(curl) {
       
        curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:5000/a");

     
        const char *data = "hello!";
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);


        res = curl_easy_perform(curl);

     
        if(res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }

  
        curl_easy_cleanup(curl);
    }

  
    curl_global_cleanup();

    return 0;
}

compiled it with gcc test.c -o test.exe -IC:\Users\MY_USERNAME\scoop\apps\curl\current\include -LC:\Users\MY_USERNAME\scoop\apps\curl\current\lib -lcurl but you can replace the paths with wherever the libcurl include directory is (i hope).

[-] litchralee@sh.itjust.works 3 points 3 weeks ago* (last edited 3 weeks ago)

Unless I'm mistaken, that first example as-written will ~~fetch~~ POST the network resource and then immediately clean up. The fact that CURLOPT_NOPROGRESS is passed means that the typical progress bar for curl in an interactive shell will be suppressed. The comment in the code even says that to make the example do something useful, you'll have to pass callback pointers, possibly by way of CURLOPT_WRITEFUNCTION or CURLOPT_WRITEDATA.

From the curl_easy_perform() man page:

A network transfer moves data to a peer or from a peer. An application tells libcurl how to receive data by setting the CURLOPT_WRITEFUNCTION and CURLOPT_WRITEDATA options. To tell libcurl what data to send, there are a few more alternatives but two common ones are CURLOPT_READFUNCTION and CURLOPT_POSTFIELDS.

[-] Irelephant@lemm.ee 1 points 3 weeks ago

Ah, right.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

struct MemoryStruct {
    char *memory;
    size_t size;
};

size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, struct MemoryStruct *userp) {
    size_t realsize = size * nmemb;
    userp->memory = realloc(userp->memory, userp->size + realsize + 1);
    if(userp->memory == NULL) {
        return 0;
    }
    memcpy(&(userp->memory[userp->size]), contents, realsize);
    userp->size += realsize;
    userp->memory[userp->size] = 0;
    return realsize;
}

int main(int argc, char *argv[]) {
    CURLcode ret;
    CURL *hnd;
    struct MemoryStruct chunk;

    chunk.memory = malloc(1);
    chunk.size = 0;

    hnd = curl_easy_init();
    if(hnd) {
        curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
        curl_easy_setopt(hnd, CURLOPT_URL, "https://pastebin.com/api/api_post.php");
        curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
        curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "api_dev_key=API_KEY_HERE&api_paste_code=test&api_option=paste");
        curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)81);
        curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/8.9.1");
        curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
        curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
        curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
        curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(hnd, CURLOPT_WRITEDATA, (void *)&chunk);

        ret = curl_easy_perform(hnd);

        if(ret != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(ret));
        } else {
            printf("%s\n", chunk.memory);
        }

        curl_easy_cleanup(hnd);
        free(chunk.memory);
    } else {
        fprintf(stderr, "Failed to initialize CURL\n");
    }

    return (int)ret;
}

Finished it, i think. Still does "nothing"

edit: probably shouldn't include my api key with it.

[-] litchralee@sh.itjust.works 2 points 3 weeks ago* (last edited 3 weeks ago)

I'm on mobile so I can't compile this myself, but can you clarify on what you're observing? Does "nothing" mean no output to stdout and stderr? Or that you did get an error message but it's not dispositive as to what libcurl was doing? Presumably the next step would be to validate that the program is executing at all, either with a debugger or printf-style debug statements at all junctures.

Please include as much detail as you can, since this is now more akin to a bug report.

EDIT: wait a sec. What exactly is this example code meant to do? The Pastebin API call suggests that this is meant to upload a payload to the web, not pull it down. But CURLOPT_WRITEFUNCTION is for receiving data from a URI. What is your intention with running this example program?

[-] Irelephant@lemm.ee 1 points 3 weeks ago

I'm trying to send a post request to Pastebins api to make a paste. This is one of the first programs I have tried to write with libcurl, so its probably wrong.

[-] atzanteol@sh.itjust.works 1 points 3 weeks ago

What exactly are you expecting to happen? Have you written code before?

[-] Irelephant@lemm.ee 1 points 3 weeks ago

I have written code before. I just started with C recently. I am expecting it to do literally anything at this point, but for some reason whenever I use the libcurl library literally nothing happens that i can observe.

[-] e0qdk@reddthat.com 3 points 3 weeks ago* (last edited 3 weeks ago)

As a sanity check, does this work?

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>

size_t save_to_disk(char* ptr, size_t size, size_t nmemb, void* user_data)
{
    /* according to curl's docs size is always 1 */
    
    FILE* fp = (FILE*)user_data;
    fprintf(stderr, "got %lu bytes\n", nmemb);
    return fwrite(ptr, size, nmemb, fp);
}

int main(int argc, char* argv[])
{
    char errbuf[CURL_ERROR_SIZE];
    FILE* fp = NULL;
    CURLcode res;
    
    CURL* curl = curl_easy_init();
    
    if(!curl)
    {
        fprintf(stderr, "Failed to initialize curl\n");
        return EXIT_FAILURE;
    }
    
    fp = fopen("output.data", "wb");
    if(!fp)
    {
        fprintf(stderr, "Failed to open file for writing!");
        return EXIT_FAILURE;
    }
    
    curl_easy_setopt(curl, CURLOPT_URL, "https://www.wikipedia.org");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, save_to_disk);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
    
    errbuf[0] = 0;  /* set error buffer to empty string */
    res = curl_easy_perform(curl);
    
    if(fp)
    {
        fclose(fp);
        fp = NULL;
    }
    
    if(res != CURLE_OK)
    {
        fprintf(stderr, "error code   : %d\n", res);
        fprintf(stderr, "error buffer : %s\n", errbuf);
        fprintf(stderr, "easy_strerror: %s\n", curl_easy_strerror(res));
        
        return EXIT_FAILURE;
    }
    else
    {
        fprintf(stderr, "\nDone\n");
        return EXIT_SUCCESS;
    }
}

That should write a file called output.data with the HTML from https://www.wikipedia.org and print out the number of bytes each time the write callback receives data for processing.

On my machine, it prints the following when it works successfully (byte counts may vary for you):

got 13716 bytes
got 16320 bytes
got 2732 bytes
got 16320 bytes
got 16320 bytes
got 128 bytes
got 16320 bytes
got 16320 bytes
got 1822 bytes

Done

If I change the URL to nonsense instead to make it fail, it prints text like this on my system:

error code   : 6
error buffer : Could not resolve host: nonsense
easy_strerror: Couldn't resolve host name

Edit: corrected missing line in source (i.e. added line with CURLOPT_ERRORBUFFER which is needed to get extra info in the error buffer on failure, of course)

Edit 2: tweaks to wording to try to be more clear

[-] Irelephant@lemm.ee 3 points 3 weeks ago
PS C:\Users\USERNAME\3ds> gcc test.c -o test.exe -IC:\Users\22.tom.carroll\scoop\apps\curl\current\include -LC:\Users\22.tom.carroll\scoop\apps\curl\current\lib -lcurl
PS C:\Users\USERNAMEl\3ds> ./test.exe
PS C:\Users\USERNAME3ds> ls


    Directory: C:\Users\USERNAME\3ds


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        19/11/2024     20:48                c
-a----        29/11/2024     21:35           1880 file.c
-a----        29/11/2024     22:52           1409 test.c
-a----        29/11/2024     22:52         236221 test.exe


PS C:\Users\USERNAME\3ds>

Its not working unfortunatly.

[-] e0qdk@reddthat.com 4 points 3 weeks ago

Does hello world work? You should've gotten at least some console output.

#include <stdio.h>

int main()
{
    fprintf(stderr, "Hello world\n");
    return 0;
}
[-] Irelephant@lemm.ee 3 points 3 weeks ago

That works perfectly

PS C:\Users\username\3ds> gcc test.c -o test.exe 
PS C:\Users\username\3ds> ./test.exe
    Hello world

[-] e0qdk@reddthat.com 5 points 3 weeks ago

Try adding some prints to stderr through my earlier test program then and see if you can find where it stops giving you output. Does output work before curl_easy_init? After it? Somewhere later on?

Note that I did update the program to add the line with CURLOPT_ERRORBUFFER -- that's not strictly needed, but might provide more debug info if something goes wrong later in the program. (Forgot to add the setup line initially despite writing the rest of it... 🤦‍♂️️)

You could also try adding curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); to get it to explain more details about what it's doing internally if you can get it to print output at all.

[-] thingsiplay@beehaw.org 1 points 3 weeks ago

Does your Antivirus or Firewall prevents it from accessing the internet maybe?

[-] Irelephant@lemm.ee 1 points 3 weeks ago

I checked, and it doesn't.

this post was submitted on 29 Nov 2024
-8 points (25.0% liked)

Programming

17672 readers
51 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 2 years ago
MODERATORS