C++ 有没有办法忽略信号签名?
我正在尝试用相同的用户函数回调连接一些小部件。在某些情况下,信号具有不同的特征码 搜索时我发现gtk_信号_连接_已满,我想 例如,我的代码:C++ 有没有办法忽略信号签名?,c++,gtk3,C++,Gtk3,我正在尝试用相同的用户函数回调连接一些小部件。在某些情况下,信号具有不同的特征码 搜索时我发现gtk_信号_连接_已满,我想 例如,我的代码: int MyObject::connect() { callback_object .... // Create the callback int ret = g_signal_connect(instance, "clicked", G_CALLBACK (connect_callback), callback_object)
int MyObject::connect()
{
callback_object ....
// Create the callback
int ret = g_signal_connect(instance, "clicked", G_CALLBACK (connect_callback), callback_object);
int ret = g_signal_connect(instance, "button-release-event", G_CALLBACK (connect_callback), callback_object);
// Return handler id
return ret;
}
void MyObject::connect_callback(GObject *passedInstance, gpointer param1, gpointer param2)
{
// Return to st_callback
struct st_callback *callback_object = (struct st_callback *) param2;
if(sizeof(param1) == 0) {
callback_object = (struct st_callback *) param1;
}
}
我可以像那样“抽象”用户函数吗?如果可以的话,如何获得额外的参数,比如GdkEvent或GdkEventButton,或gchar
编辑
-这个问题是GTK+问题,因为在第一个g_信号连接中,param1是我的结构。我很好,我知道我的结构要倒转。在第二个g_信号_connect中,param1是一个GdkEventButton。这也没关系,因为我知道这是一个很好的反省。但是,如果我不知道param1是我的结构,如果它是一个GdkEvent,GdkEventButton,gchar,或者所有其他可能的sinal签名,怎么做呢
编辑2
-我在上找到了这个信息
闭包允许被调用方获取回调参数的类型,这意味着语言绑定不必为每个回调类型编写单独的胶水
这看起来非常适合我要找的东西,但我没有找到比这更好的东西
编辑3
有了ebassi ideia about,我需要的是g_信号查询。我这样做是为了抽象:
1-使用g_signal_query查询信号参数,设置到my structure中与回调用户_数据一起传递
2-使用g_cclosure_new_swap和g_signal_connect_Close连接,将gpointer user_数据设置为第一个参数
3-创建如下回调:connect\u回调(gpointer user\u data,…)
,带有变量参数列表
4-在回调中,使用自定义+g_信号_查询结果返回我的结构
5-循环到GSignalQuery的param_类型,验证每个基本类型
6-使用正确的类型获取va_参数
调用回调函数的完整代码
// Create gpoint param
struct st_callback *callback_object = (struct st_callback *)malloc(sizeof(struct st_callback));
memset(callback_object, 0, sizeof(struct st_callback));
callback_object->callback_name = callback_name;
callback_object->callback_params = callback_params;
// Get params of signal
GSignalQuery signal_info;
g_signal_query(g_signal_lookup (callback_signal, G_OBJECT_TYPE (instance)), &signal_info);
// Save
callback_object->signal_id = signal_info.signal_id;
callback_object->signal_name = signal_info.signal_name;
callback_object->itype = signal_info.itype;
callback_object->signal_flags = signal_info.signal_flags;
callback_object->return_type = signal_info.return_type;
callback_object->n_params = signal_info.n_params;
callback_object->param_types = signal_info.param_types;
GClosure *closure;
closure = g_cclosure_new_swap (G_CALLBACK (connect_callback), callback_object, NULL);
int ret = g_signal_connect_closure (instance, callback_event, closure, TRUE);
static bool connect_callback(gpointer user_data, ...)
{
// Return to st_callback
struct st_callback *callback_object = (struct st_callback *) user_data;
// get parameters count
int param_count = callback_object->n_params;
va_list ap;
va_start(ap, param_count);
// loop paramters
for (int i=0; i<param_count; i++) {
switch (G_TYPE_FUNDAMENTAL(callback_object->param_types[i])) {
case G_TYPE_CHAR:
break;
case G_TYPE_UCHAR:
break;
case G_TYPE_STRING:
{
char *path = va_arg(ap, char *);
break;
}
case G_TYPE_OBJECT:
break;
case G_TYPE_POINTER:
break;
case G_TYPE_INTERFACE:
break;
case G_TYPE_PARAM:
break;
case G_TYPE_BOXED:
{
// Example, try to cast correct boxed
GdkEvent *e = va_arg(ap, GdkEvent *);
break;
}
}
}
va_end(ap);
}
回拨电话呢
// Create gpoint param
struct st_callback *callback_object = (struct st_callback *)malloc(sizeof(struct st_callback));
memset(callback_object, 0, sizeof(struct st_callback));
callback_object->callback_name = callback_name;
callback_object->callback_params = callback_params;
// Get params of signal
GSignalQuery signal_info;
g_signal_query(g_signal_lookup (callback_signal, G_OBJECT_TYPE (instance)), &signal_info);
// Save
callback_object->signal_id = signal_info.signal_id;
callback_object->signal_name = signal_info.signal_name;
callback_object->itype = signal_info.itype;
callback_object->signal_flags = signal_info.signal_flags;
callback_object->return_type = signal_info.return_type;
callback_object->n_params = signal_info.n_params;
callback_object->param_types = signal_info.param_types;
GClosure *closure;
closure = g_cclosure_new_swap (G_CALLBACK (connect_callback), callback_object, NULL);
int ret = g_signal_connect_closure (instance, callback_event, closure, TRUE);
static bool connect_callback(gpointer user_data, ...)
{
// Return to st_callback
struct st_callback *callback_object = (struct st_callback *) user_data;
// get parameters count
int param_count = callback_object->n_params;
va_list ap;
va_start(ap, param_count);
// loop paramters
for (int i=0; i<param_count; i++) {
switch (G_TYPE_FUNDAMENTAL(callback_object->param_types[i])) {
case G_TYPE_CHAR:
break;
case G_TYPE_UCHAR:
break;
case G_TYPE_STRING:
{
char *path = va_arg(ap, char *);
break;
}
case G_TYPE_OBJECT:
break;
case G_TYPE_POINTER:
break;
case G_TYPE_INTERFACE:
break;
case G_TYPE_PARAM:
break;
case G_TYPE_BOXED:
{
// Example, try to cast correct boxed
GdkEvent *e = va_arg(ap, GdkEvent *);
break;
}
}
}
va_end(ap);
}
静态布尔连接回调(gpointer用户数据,…)
{
//返回st_回调
struct st_callback*callback_object=(struct st_callback*)用户数据;
//获取参数计数
int param_count=回调对象->n_参数;
va_列表ap;
va_启动(ap、参数计数);
//循环参数
对于(int i=0;iparam_类型[i])){
案例G_类型_字符:
打破
案例G_类型_UCHAR:
打破
案例G_类型_字符串:
{
char*path=va_arg(ap,char*);
打破
}
案例G_类型_对象:
打破
案例G_类型_指针:
打破
案例G_类型_接口:
打破
案例G_类型_参数:
打破
箱子G_类型_装箱:
{
//例如,尝试铸造正确的盒装
GdkEvent*e=va_arg(ap,GdkEvent*);
打破
}
}
}
va_端(ap);
}
需要更正return和boxed cast,但是有了它,我可以很好地工作您不应该对不同类型的回调使用相同的函数。一些回调采用不同的参数,其他回调具有不同的返回值-例如,在您的示例中,
clicked
不返回任何内容,而button press event
返回布尔值
如果您有需要在不同信号处理程序中执行的通用代码,请编写一个函数,然后从不同的处理程序中调用它。对于不同类型的回调,不应使用相同的函数。一些回调采用不同的参数,其他回调具有不同的返回值-例如,在您的示例中,
clicked
不返回任何内容,而button press event
返回布尔值
如果您有需要在不同的信号处理程序中执行的通用代码,请编写一个函数,然后从不同的处理程序中调用它。也许您的回调采用了包含所有可能属性甚至联合的结构。但是进行此验证的正确方法是什么?什么类型的额外参数和参数是我的结构,我从来没有使用过GTK库,但是C++的方式是通过一个函子,即一个具有<代码>操作程序()/<代码>重载的类/结构,并且只调用操作程序()。参数将已设置为类成员。。如果这是你想要达到的,我可以把它作为一个答案。老实说,我认为你的问题不属于GTK,它听起来像是一个普通的C++问题,如何解决它。试着用更高的术语解释这个问题(我不知道G_类型是什么)。如果你这样做(抽象你的问题到C++一个,而不是GTK一个),那么你可能会从C++程序员那里得到更多的帮助,而这些程序员对GTK一无所知,但是向导们正在使用模板,元编程来解决你的问题。或者类似于我链接到的代码。也许让回调采用包含所有可能属性甚至联合的结构。但是,进行这种验证的正确方法是什么?什么类型的额外参数和参数是我的结构,我从来没有使用过GTK库,但是C++的方式是通过一个函子,即一个具有<代码>操作程序()/<代码>重载的类/结构,并且只调用操作程序()。参数将已设置为类成员。。如果这是你想要达到的,我可以把它作为一个答案。老实说,我认为你的问题不属于GTK,它听起来像是一个普通的C++问题,如何解决它。试着用更高的术语解释这个问题(我不知道G_类型是什么)。如果你这样做(抽象你的问题到C++一个,而不是GTK一个),那么你可能会从C++程序员那里得到更多的帮助,而这些程序员对GTK一无所知,但是巫师们会用模板、元程序或类似的代码来向你的问题提出解决方案。我计划从txt外部文件配置信号。用户可以通过l添加信号名称行