C++ std::function.target返回null
我正在使用cURL通过http下载文件。cURL需要一个回调来处理数据,我的类中有一个回调,我使用std::bind和std::function的组合来创建一个具有适当类型的函数C++ std::function.target返回null,c++,c++11,curl,C++,C++11,Curl,我正在使用cURL通过http下载文件。cURL需要一个回调来处理数据,我的类中有一个回调,我使用std::bind和std::function的组合来创建一个具有适当类型的函数 size_t NetworkResource::writeFunction(char *ptr,size_t size,size_t nmemb,void *userdata) { ... } void NetworkResource::loadFunction(void) { using namespace
size_t NetworkResource::writeFunction(char *ptr,size_t size,size_t nmemb,void *userdata)
{
...
}
void NetworkResource::loadFunction(void)
{
using namespace std::placeholders;
typedef size_t CurlCallback(char*,size_t,size_t,void*);
auto function=std::function<CurlCallback>(std::bind(&NetworkResource::writeFunction,this,_1,_2,_3,_4)).target<CurlCallback*>();
CURL *curl=curl_easy_init();
CURLcode err;
...
err=curl_easy_setopt(curl,CURLOPT_WRITEDATA,nullptr);
if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl;
err=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,*function);
if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl;
...
}
size\t NetworkResource::writeFunction(char*ptr、size\t size、size\t nmemb、void*userdata)
{
...
}
void NetworkResource::loadFunction(void)
{
使用名称空间std::占位符;
typedef size\u t(char*、size\u t、size\u t、void*);
auto function=std::function(std::bind(&NetworkResource::writeFunction,this,_1,_2,_3,_4)).target();
CURL*CURL=CURL_easy_init();
代码错误;
...
err=curl\u easy\u setopt(curl,CURLOPT\u WRITEDATA,nullptr);
如果(err!=CURLE_OK)std::cout
最后一个参数userdata
可以通过调用来设置。使用此参数可以传递指向NetworkResource
实例的指针(该this
指针)
对于write\u callback
,创建一个执行所需功能的静态成员函数
class NetworkResource
{
// ...
static size_t writeFunction(char *ptr,size_t size,size_t nmemb,void *userdata);
};
size_t NetworkResource::writeFunction(char *ptr,size_t size,size_t nmemb,void *userdata)
{
// userdata points to the NetworkResource instance
auto res = static_cast<NetworkResource *>(userdata);
// use res and the remaining function arguments to handle the call
}
void NetworkResource::loadFunction(void)
{
CURL *curl=curl_easy_init();
CURLcode err;
...
err=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,&NetworkResource::writeFunction);
if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl;
err=curl_easy_setopt(curl,CURLOPT_WRITEDATA,static_cast<void *>(this));
if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl;
...
}
类网络资源
{
// ...
静态大小写函数(char*ptr、size\t size、size\t nmemb、void*userdata);
};
大小网络资源::写函数(char*ptr、大小、大小nmemb、void*userdata)
{
//userdata指向NetworkResource实例
auto res=静态_cast(userdata);
//使用res和剩余的函数参数来处理调用
}
void NetworkResource::loadFunction(void)
{
CURL*CURL=CURL_easy_init();
代码错误;
...
err=curl\u easy\u setopt(curl、CURLOPT\u WRITEFUNCTION和NetworkResource::WRITEFUNCTION);
如果(err!=CURLE_OK)std::cout今天我遇到了这个问题,我可以建议您一个解决方案:
这是我的演示
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <thread>
#include <unistd.h>
#include <string.h>
#include <functional>
using namespace std;
class foo {
public:
virtual int sum(int a, int b) { return -1; };
};
class bar : public foo{
public:
virtual int sum(int a, int b) override;
};
int bar::sum(int a, int b) {
return a + b;
}
int main() {
bar *b = new bar();
std::function<int(int, int)> f = std::bind(&bar::sum, b, std::placeholders::_1, std::placeholders::_2);
printf("result : %d\n", f(1, 3));
printf("result : %s\n", f.target_type().name());
printf("null : %d\n", (*f.target<int(int, int)>())(1, 2));
printf("null : %d\n", f);
return 0;
}
返回类型必须为null,因为int(int,int)
不等于内部类型
要获取std::function
的内部类型,应首先使用target_type().name()
,如下所示:
printf("%s\n", f.target_type().name());
c++filt -t St5_BindIFSt7_Mem_fnIM3barFiiiEEPS1_St12_PlaceholderILi1EES6_ILi2EEEE
int main() {
bar *b = new bar();
std::function<int(int, int)> f = std::bind(&bar::sum, b, std::placeholders::_1, std::placeholders::_2);
printf("result : %d\n", f(1, 3));
printf("result : %s\n", f.target_type().name());
printf("null : %d\n", (*f.target<std::_Bind<std::_Mem_fn<int (bar::*)(int, int)> (bar*, std::_Placeholder<1>, std::_Placeholder<2>)>>())(1, 2));
printf("null : %d\n", f);
return 0;
}
结果是:
St5_BindIFSt7_Mem_fnIM3barFiiiEEPS1_St12_PlaceholderILi1EES6_ILi2EEEE
接下来,您可以使用c++filt
解析此符号,如下所示:
printf("%s\n", f.target_type().name());
c++filt -t St5_BindIFSt7_Mem_fnIM3barFiiiEEPS1_St12_PlaceholderILi1EES6_ILi2EEEE
int main() {
bar *b = new bar();
std::function<int(int, int)> f = std::bind(&bar::sum, b, std::placeholders::_1, std::placeholders::_2);
printf("result : %d\n", f(1, 3));
printf("result : %s\n", f.target_type().name());
printf("null : %d\n", (*f.target<std::_Bind<std::_Mem_fn<int (bar::*)(int, int)> (bar*, std::_Placeholder<1>, std::_Placeholder<2>)>>())(1, 2));
printf("null : %d\n", f);
return 0;
}
结果是:
std::_Bind<std::_Mem_fn<int (bar::*)(int, int)> (bar*, std::_Placeholder<1>, std::_Placeholder<2>)>
std::\u绑定
上面的符号是您应该在std::function
中编写的,因此最后的代码如下:
printf("%s\n", f.target_type().name());
c++filt -t St5_BindIFSt7_Mem_fnIM3barFiiiEEPS1_St12_PlaceholderILi1EES6_ILi2EEEE
int main() {
bar *b = new bar();
std::function<int(int, int)> f = std::bind(&bar::sum, b, std::placeholders::_1, std::placeholders::_2);
printf("result : %d\n", f(1, 3));
printf("result : %s\n", f.target_type().name());
printf("null : %d\n", (*f.target<std::_Bind<std::_Mem_fn<int (bar::*)(int, int)> (bar*, std::_Placeholder<1>, std::_Placeholder<2>)>>())(1, 2));
printf("null : %d\n", f);
return 0;
}
intmain(){
bar*b=新的bar();
函数f=std::bind(&bar::sum,b,std::占位符::_1,std::占位符::_2);
printf(“结果:%d\n”,f(1,3));
printf(“结果:%s\n”,f.target_type().name());
printf(“null:%d\n”,(*f.target())(1,2));
printf(“空:%d\n”,f);
返回0;
}
如果您正试图以这种方式将成员函数转换为静态函数,那么它将不起作用。是否有理由不CURLOPT_WRITEDATA
将此
传递给静态回调,在解包指针后将调用转发给非静态成员?为什么不起作用?std::function.target returns是指向函数指针的指针。我不是将std::function传递给curl\u easy\u setopt,而是传递函数指针。std::function.target返回指向函数指针的指针。