Sté*_*ane 2 c++ gtk lambda callback
我想g_signal_connect()在Gtk +中使用lambda 。传统上,像这样工作来设置回调函数:
#include <gtk/gtk.h>
#include <iostream>
void my_callback(GtkApplication *app, gpointer user_data)
{
std::cout << "test1" << std::endl;
}
void test1()
{
GtkApplication *app = gtk_application_new(nullptr, G_APPLICATION_NON_UNIQUE);
void * data = nullptr; // simple example
g_signal_connect(app, "activate", G_CALLBACK(my_callback), data);
}
Run Code Online (Sandbox Code Playgroud)
编译上面的测试g++ $(pkg-config --cflags --libs gtk+-3.0) test.cpp以获取必要的GTK + -3.0定义。
在尝试转换my_callback1()为lambda时,我尝试了以下方法:
void test2()
{
GtkApplication *app = gtk_application_new(nullptr, G_APPLICATION_NON_UNIQUE);
void * data = nullptr; // simple example
// use lambda instead of call to explicit function
g_signal_connect(app, "activate",
G_CALLBACK(
[](GtkApplication *application, gpointer user_data)
{
std::cout << "test2" << std::endl;
}
), data);
}
Run Code Online (Sandbox Code Playgroud)
test2()上面的代码产生以下编译错误:
/usr/include/glib-2.0/gobject/gclosure.h:70:41: error: invalid cast
from type ‘test2()::<lambda(GtkApplication*, gpointer)>’
to type ‘GCallback {aka void (*)()}’
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以将C ++ lambda指定为回调函数?我不了解解决此“无效类型转换”需要什么。
当您查看的定义时G_CALLBACK,您会发现它只是对的强制转换void (*)()。这是Gtk +在接收到的指针类型上采用类型擦除的形式,从而删除了参数列表。
lambda定义(关闭)对象类型。这不是功能。尽管无捕获lambda确实具有对函数指针的隐式转换运算符,但该指针具有与lambda的参数列表匹配的签名。
因此,您可以将lambda转换为void(*)(GtkApplication*, gpointer),但不能将其直接转换为a ,void (*)()因为它是完全不相关的类型。
解决方法是先将lambda转换为函数指针类型,然后再将其输入进行转换G_CALLBACK。做到这一点的一个巧妙技巧是+在lambda之前附加一个:
g_signal_connect(app, "activate",
G_CALLBACK(
+[](GtkApplication *application, gpointer user_data)
{
std::cout << "test2" << std::endl;
}
), data);
Run Code Online (Sandbox Code Playgroud)
由于一元+不会在lambda上重载,因此编译器会有所帮助,并为我们进行了指针转换(一元+可能适用于此)。在那之后,宏中的强制转换应该起作用。