将额外参数传递给 libcurl CURLOPT_READFUNCTION 回调
程序
读出文本文件并通过电子邮件发送其内容
原始代码(在Sehe的帮助下)
https://gist.github.com/1342118#file_test.cpp
问题:
我尝试多次运行该应用程序使用线程,为每个线程使用不同的文本文件。这意味着我不能再使用全局向量,因为线程 3 可能会在线程 1 仍在处理该向量时添加/更改该向量。这意味着这一行变得有问题:
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
这调用了这个函数:
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct WriteThis *pooh = (struct WriteThis *)userp;
if(size*nmemb < 1)
return 0;
if (pooh->counter < text.size())
{
const std::string& data = text[pooh->counter];
memcpy(ptr, data.data(), data.length());
pooh->counter++; /* advance pointer */
return data.length();
}
return 0; /* no more data left to deliver */
}
正如您所看到的,它使用全局定义的向量“文本”。我以为我可以通过简单地在该函数(read_callback)中创建向量来修复它,但由于我现在使用线程,文件名不再是硬编码的,所以我最终不得不传递一个变量。
Curl 似乎填充了 read_callback 自动接受的变量,那么这是如何完成的呢?
只是为了澄清一下,这就是我现在所拥有的:
std::vector<string> read_text(char* fname)
{
std::ifstream myfile (fname);
std::vector<string> text;
std::string line;
while (std::getline(myfile, line))
{
text.push_back(line + '\n');
}
return text;
}
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
std::vector<string> text;
text = read_text(textfilename);
struct WriteThis *pooh = (struct WriteThis *)userp;
if(size*nmemb < 1)
return 0;
if (pooh->counter < text.size())
{
const std::string& data = text[pooh->counter];
memcpy(ptr, data.data(), data.length());
pooh->counter++; /* advance pointer */
return data.length();
}
return 0; /* no more data left to deliver */
}
但是 read_text 不起作用,因为 textfilename 尚未传递给该函数。
The program
Reads out a textfile and emails it's contents
The original code (with help of Sehe)
https://gist.github.com/1342118#file_test.cpp
The problem:
I am trying to run the application multiple times using threading, using a different textfile for each thread. This means I can no longer use a global vector because thread 3 may add to / alter this vector while thread 1 is still working on it. This means this line is becoming problematic:
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
This calls this function:
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct WriteThis *pooh = (struct WriteThis *)userp;
if(size*nmemb < 1)
return 0;
if (pooh->counter < text.size())
{
const std::string& data = text[pooh->counter];
memcpy(ptr, data.data(), data.length());
pooh->counter++; /* advance pointer */
return data.length();
}
return 0; /* no more data left to deliver */
}
As you can see it uses the globally defined vector "text". I thought I could fix it by simply making the vector inside that function (read_callback) but since I'm using threading now, the filename is no longer hard coded so I end up having to pass a variable anyway.
Curl seems to fill in the variables that read_callback accepts automatically so how is this done?
Just to clarify, here's what I have now:
std::vector<string> read_text(char* fname)
{
std::ifstream myfile (fname);
std::vector<string> text;
std::string line;
while (std::getline(myfile, line))
{
text.push_back(line + '\n');
}
return text;
}
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
std::vector<string> text;
text = read_text(textfilename);
struct WriteThis *pooh = (struct WriteThis *)userp;
if(size*nmemb < 1)
return 0;
if (pooh->counter < text.size())
{
const std::string& data = text[pooh->counter];
memcpy(ptr, data.data(), data.length());
pooh->counter++; /* advance pointer */
return data.length();
}
return 0; /* no more data left to deliver */
}
But read_text doesn't work because textfilename hasn't been passed to the function.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
再次仔细阅读 curl_easy_setopt 的文档。您可以将
CURLOPT_READDATA
设置为您的textfilename
并强制转换userp
以将其放入您的read_callback
edit
您的
userp
已实际使用;因此,您应该将textfilename
添加到WriteThis
struct
的新字段中。大多数回调函数只接受一个用户数据,但这应该足够了(因为您可以在其中打包任意内容)。Read carefully again curl_easy_setopt's documentation. You might set the
CURLOPT_READDATA
to yourtextfilename
and cast theuserp
to get it inside yourread_callback
edit
Your
userp
is actually used; so you should add thetextfilename
in a new field of yourWriteThis
struct
. Most callback functions take only one user data, but it should be enough (since you can pack arbitrary stuff in it).