C++ 有没有办法忽略信号签名?

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)

我正在尝试用相同的用户函数回调连接一些小部件。在某些情况下,信号具有不同的特征码

搜索时我发现gtk_信号_连接_已满,我想

例如,我的代码:

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添加信号名称行