3

我正在开发一个用 C 编程的 linux 应用程序,它处理 gdk pixbuf 图像,然后应该通过 ftp (libcurl) 将它们发送到远程服务器。图像使用gdk_pixbuf_save_to_buffer保存到 gchar 缓冲区中。

问题是我不知道如何将此缓冲区中的数据与 libcurl读取回调函数一起使用以将图像正确发送到远程服务器。到目前为止,我所有的尝试都在结果文件中产生了随机字节。

有一个 libcurl 读取回调函数的示例,如下所示:

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
    size_t retcode = fread(ptr, size, nmemb, stream);
    return retcode;
} 

我需要做我自己的回调函数,将 gchar 缓冲区作为输入而不是文件流,并从中读取 size*nmemb 字节并将其存储到 *ptr。

这与我之前的问题有关

4

1 回答 1

4

read_callback()是 CURL 在需要获取将上传到服务器的数据时调用的函数。想象一下,read_callback()fread(). 当被调用时,它会执行任何需要的 voodoo-mumbo-jumbo,但最终可上传的数据必须存储在*ptr缓冲区中,这是 curl 的内部缓冲区。因为您的内存缓冲区memcpy()将与 body of 一样好read_callback(),所以您根本不需要真正fread()的。

size * nmemb告诉您 curl 为单个数据块保留了多大的缓冲区。最后void*一个是由 CURLOPT_READDATA 选项设置的指针 - 它是一种随心所欲的指针,因此它可以指向包含您正在上传的数据和一些附加信息的结构例如当前的进展。

您可以将此用作示例:

#include <gdk-pixbuf/gdk-pixbuf.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <string.h>

struct transfer
{
    gchar *buf;
    gsize total;
    size_t uploaded;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *data)
{
    struct transfer * tr = data;
    size_t left = tr->total - tr->uploaded;
    size_t max_chunk = size * nmemb;
    size_t retcode = left < max_chunk ? left : max_chunk;

    memcpy(ptr, tr->buf + tr->uploaded, retcode); // <-- voodoo-mumbo-jumbo :-)

    tr->uploaded += retcode;  // <-- save progress
    return retcode;
} 

int main()
{
    GdkPixbuf * gbuffer = NULL;
    GError * error = NULL;
    gchar * buffer;
    gsize size;
    g_type_init();
    gbuffer = gdk_pixbuf_new_from_file("g.png", &error);
    gdk_pixbuf_save_to_buffer(gbuffer, &buffer, &size, "jpeg", &error, NULL);

    struct transfer tr = {buffer, size, 0};

    CURL *easyhandle = curl_easy_init();
    curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, read_callback); 
    curl_easy_setopt(easyhandle, CURLOPT_READDATA, &tr); // <-- this will be *data in read_callback()
    curl_easy_setopt(easyhandle, CURLOPT_UPLOAD, 1L); 
    curl_easy_setopt(easyhandle, CURLOPT_URL, "http://example.com/upload.php");
    CURLcode rc = curl_easy_perform(easyhandle);
}
于 2012-02-26T22:24:08.467 回答