如何在回调中使用结构的参数化成员函数?

How to use parametrized member function of a struct in callback?

我有一个类似于下面的结构

struct dc_callback
{ 
    int
    my_configure_event(
        GtkWidget *widget,
        GdkEventConfigure *event,
        struct LoadData *myData)
    {
        ...others

        return TRUE;
    }

    //Parametrized Constructor 
    int
    my_draw(
        GtkWidget *widget,
        cairo_t *cr,
        struct LoadData *myData)
    {
        ...others
        return TRUE;
    }
};

它有两个参数化成员函数,我打算从 g_signal_connect 调用第 n 次。

main(){
    int i;
    dc_callback dc_callback_instance[nth];
    for(i=0;i<nth;i++){
        g_signal_connect(widget_list[i],"draw",G_CALLBACK(dc_callback_instance[i].my_draw),myData);
        g_signal_connect(widget_list[i],"configure-event",G_CALLBACK(dc_callback_instance[i].my_configure_event),myData);
    }
}

但是,在编译期间,我收到有关无效使用成员函数的错误 int dc_callback::my_draw(args)。它要求我添加 () 但无法完成,因为 G_CALLBACK 接受没有附加参数的函数名称。

我该如何完成?

G_CALLBACK 需要一个(非成员)函数指针,而您没有使用正确的语法来传递函数指针。然而,还有一个更大的问题:函数指针和成员函数指针在C++中是不同的概念。您不能将成员函数指针传递给需要标准函数指针的接口。 那么,如何将回调的调用与您的 dc_callback 实例相关联?

传统上,在使用 C 风格 API 时,您必须为将您的实例(和任何额外数据)作为 void* 参数的回调提供一个免费函数。然后在回调中,您可以将 void* 转换回原始类型。在您的情况下,这可能类似于:

struct CallbackData {
    dc_callback& dc_callback_inst;
    Foo otherData; // whatever else you need to capture here
};

void my_draw_cb(void* data) { // g_signal_connect might pass more params to cb in addition to data
    CallbackData& cbData = *(CallbackData*)data;
    cbData->dc_callback_inst.my_draw(cbData->otherData);
}

// ...
for(i=0;i<nth;i++){
    CallbackData cbData{dc_callback_instance[i], myData};
    g_signal_connect(widget_list[i],"draw",G_CALLBACK(&my_draw_cb),cbData);
    // ...
}

@0x5453 的答案是正确的,除了 my_draw_cbk 和它的调用:应该是

gboolean my_draw_cbk ( GtkWidget *widget,
        cairo_t *cr,
        struct CallbackData *cbData)
{
    cbData->dc_callback_inst.my_draw(widget, cr, cbData->otherData);
    return TRUE;
}

并连接信号:

 // cbData shall be free with g_free when no longer needed
 CallbackData* cbData = g_new(CallbackData, 1); 
 // set the cbData values..
 g_signal_connect(widget_list[i],"draw",G_CALLBACK(my_draw_cb),cbData);