Как использовать параметризованную функцию-член структуры в обратном вызове? - PullRequest
0 голосов
/ 10 октября 2019

У меня есть структура, похожая на приведенную ниже

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 принимает имя функции без присоединенного аргумента.

Как это сделать?

Ответы [ 2 ]

2 голосов
/ 10 октября 2019

Ответ @ 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);
1 голос
/ 10 октября 2019

G_CALLBACK ожидает (не-член) указатель на функцию, и вы не используете правильный синтаксис для передачи указателя на функцию. Однако есть большая проблема: указатели на функции и указатели на функции-члены - это разные понятия в C ++. Вы не можете передать указатель на функцию-член в интерфейс, который ожидает стандартный указатель на функцию. Итак, как связать вызов обратного вызова с вашим экземпляром dc_callback?

Традиционно, при работе с API в стиле C, вы должны предоставить бесплатную функцию для обратного вызова, который принимает ваш экземпляр (и любые дополнительныеданные) в качестве параметра 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);
    // ...
}
...