Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用带有函子结构的libuv代替函数回调_C++_Libuv - Fatal编程技术网

C++ 使用带有函子结构的libuv代替函数回调

C++ 使用带有函子结构的libuv代替函数回调,c++,libuv,C++,Libuv,有人知道为什么在使用函子结构而不是实际函数作为回调时libuv会出错吗。在下面的示例中,我创建了要使用的结构CB,而不是连接CB。segfault在运算符()中时发生 #包括 #包括 #包括 uv_buf_t alloc_缓冲区(uv_handle_t*handle,size_t size); 无效连接\u cb(uv\u流\u t*服务器,int状态); 无效读取cb(uv_流_t*流、ssize_t nread、uv_buf_t buf); 结构CB{ 国家*国家; CB(州*州):州(州{

有人知道为什么在使用函子结构而不是实际函数作为回调时libuv会出错吗。在下面的示例中,我创建了要使用的结构CB,而不是连接CB。segfault在运算符()中时发生

#包括
#包括
#包括
uv_buf_t alloc_缓冲区(uv_handle_t*handle,size_t size);
无效连接\u cb(uv\u流\u t*服务器,int状态);
无效读取cb(uv_流_t*流、ssize_t nread、uv_buf_t buf);
结构CB{
国家*国家;
CB(州*州):州(州{}
void操作符(){
uv_tcp_t*客户端=(uv_tcp_t*)malloc(sizeof(uv_tcp_t));
/*如果状态不为零,则存在错误*/
如果(状态==-1){
printf(“错误2\n”);
}
/*初始化新客户端*/
uv_tcp_init(循环,客户端);
/*现在,让我们将客户机绑定到用于收入的服务器*/
如果(uv_接受(服务器,(uv_流_t*)客户端)==0){
/*从流开始读取*/
int r=uv_读取_开始((uv_流_t*)客户端,(uv_分配_cb)分配缓冲区,读取_cb);
if(r){
printf(“错误3\n”);
}
状态->onConnect();
}否则{
/*出现错误时关闭客户端流*/
uv\u close((uv\u handle\u t*)客户端,NULL);
}
}
};
CB;
uv_tcp_t服务器;
uv_环_t*环;
int main(){
loop=uv_default_loop();
/*将人可读的ip地址转换为c结构*/
地址中的结构sockaddr\u;
uv_ip4_地址(“127.0.0.1”、3005和地址);
/*初始化服务器*/
uv_tcp_init(循环和服务器);
/*将服务器绑定到上面的地址*/
uv_tcp_绑定(&server,(const struct sockaddr*)&addr,0);
/*让服务器监听新连接的地址*/
int r=uv_侦听((uv_流_t*)和服务器,128,(uv_连接_cb)和cb);
if(r){
printf(“错误1\n”);
返回-1;
}
/*执行队列中的所有任务*/
返回uv_运行(循环,uv_运行默认值);
}
/**
*对每个新连接执行的回调。
*/
无效连接\u cb(uv\u流\u t*服务器,int状态){
/*在conn上动态分配新的客户端流对象*/
uv_tcp_t*客户端=(uv_tcp_t*)malloc(sizeof(uv_tcp_t));
/*如果状态不为零,则存在错误*/
如果(状态==-1){
printf(“错误2\n”);
}
/*初始化新客户端*/
uv_tcp_init(循环,客户端);
/*现在,让我们将客户机绑定到用于收入的服务器*/
如果(uv_接受(服务器,(uv_流_t*)客户端)==0){
/*从流开始读取*/
//int r=uv_读取_开始((uv_流_t*)客户端,(uv_分配_cb)分配缓冲区,读取_cb);
int r=0;
if(r){
printf(“错误3\n”);
}
}否则{
/*出现错误时关闭客户端流*/
uv\u close((uv\u handle\u t*)客户端,NULL);
}
}
/**
*在每个可读状态上执行的回调。
*/
无效读取\u cb(uv\u流\u t*流、ssize\u t nread、uv\u buf\u t buf){
/*为新的写入任务动态分配内存*/
uv_write_t*req=(uv_write_t*)malloc(sizeof(uv_write_t));
/*如果读取字节计数器-1,则存在错误或EOF*/
如果(nread==-1){
printf(“错误4\n”);
uv_关闭((uv_句柄_t*)流,NULL);
}
/*将传入缓冲区写入同步到套接字*/
int r=uv_写入(请求、流和buf,1,空);
if(r){
printf(“错误5\n”);
}
}
/**
*分配一个可用于读取的缓冲区。
*/
uv_buf_t alloc_缓冲区(uv_handle_t*handle,size_t size){
返回uv_buf_init((char*)malloc(size),size);
}

粘贴的代码将不起作用,因为libuv在
uv\u listen
中需要一个函数指针-您提供的是指向结构的指针。此结构碰巧有一个
操作符()
,但这并不使结构的地址成为处理器可以跳转到并执行代码的地址。
operator()
与结构的任何其他方法一样,但是您可以使用
()
.operator()
调用它,使代码更具可读性。此外,由于
操作符()
是非静态的,因此它需要对
进行隐式引用,而libuv不会提供该引用,因为它不需要这样做

要实现您试图执行的操作,您应该提供一个普通的C函数回调,并将额外的上下文数据存储在句柄的
.data
字段中:

而不是:

    int r = uv_listen((uv_stream_t *) &server, 128, (uv_connection_cb)&cb);
使用:


uv句柄上的
.data
字段正是为此目的提供的。

我认为将函子传递给需要函数指针的C API是不正确的。您需要编写包装器来进行必要的转换。话虽如此,如果您使用的是c++11,则可以使用带有“无捕获”的lambda函数。但是考虑到回调的大小,这是没有意义的,也不是一件正确的事情。在这两者之间,当您没有任何状态要维护,也没有在STL算法中调用它时,为什么要使用functor进行此操作。我之所以想这样做,是因为我需要函数中的一些上下文来调用我自己的另一个回调。有没有其他方法可以在这个回调中提供一些上下文?我编辑了这个问题,使得状态是显式的,即使它是占位符。我不熟悉libuv API。理想情况下,这样的框架为调用方存储信息提供了与void*等价的东西。请找那个。否则,您需要像libuv所期望的那样,执行与函数签名相匹配的操作。
    int r = uv_listen((uv_stream_t *) &server, 128, (uv_connection_cb)&cb);
    server.data = &cb;
    int r = uv_listen((uv_stream_t *) &server, 128, [](uv_stream_t *server, int status){
        (*(CB*)server->data)(server, status);
    });