(注意:这是我认为应该问的问题的答案,而不是实际问的问题。请参阅https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)
您应该只为 libcurl 提供您自己的用户数据,而不是弄乱 C 库的内部结构,这绝不是一个好主意。您可以在CURLOPT_WRITEDATA
初始化传输时使用选项设置用户数据。
正是针对此类应用程序,libcurl 为您提供了设置自己的用户数据的可能性,而不仅仅是传递 FILE*。
粗略地说,代码看起来像这样:
// All error checking has been omitted; don't use this code as is.
// This is the userdata you'll be using
typedef struct FileWithMD5 {
FILE* file;
MD5_CTX md5_ctx;
} FileWIthMD5;
// The transfer function we'll be using
size_t write_with_md5(char *ptr, size_t size, size_t nmemb,
void *userdata);
// This function is called before the transfer is started.
// The return value needs to be passed to the finalize function.
FileWithMD5* initialize_transfer(CURL *handle, const char* filename) {
// Allocate a userdata
FileWithMD5* userdata = malloc(sizeof(*userdata));
userdata->file = fopen(filename, "w");
MD5Init(&userdata->md5_ctx);
curl_easy_setopt(handle, CURL_WRITEDATA, userdata);
curl_easy_setopt(handle, CURL_WRITEFUNCTION, write_with_md5);
return userdata;
}
// This function is called after the transfer is finished.
void finalize_transfer_and_extract_md5(CURL *handle,
FileWithMD5* userdata,
u_int8_t md5[MD5_DIGEST_LENGTH]) {
// Close the file, extract the MD5, and get rid of the userdata
close(userdata->file);
MD5Final(md5, &userdata->md5_ctx);
free(userdata);
curl_easy_setopt(handle, CURL_WRITEDATA, 0);
}
// Callback function
size_t write_with_md5(char *ptr, size_t size, size_t nmemb,
void *vuserdata) {
FileWithMD5* userdata = vuserdata;
// Write the data and update the MD5
size_t written = fwrite(ptr, size, nmemb, userdata->file);
MD5Update(&userdata->md5_ctx, (const u_int8_t*)ptr, written);
return written;
}