Указатели функции и обратные вызовы в C

Вы забыли вернуть результат в методе get. Должно было быть:

public function get(){
    return $this->db->get('dashboardutama')->result();
}
13
задан Community 23 May 2017 в 12:16
поделиться

6 ответов

Этот код компиляции и выполнения под GCC с - Стена.

#include <stdio.h>

struct event_cb;

typedef void (*event_cb_t)(const struct event_cb *evt, void *user_data);

struct event_cb
{
    event_cb_t cb;
    void *data;
};

static struct event_cb saved = { 0, 0 };

void event_cb_register(event_cb_t cb, void *user_data)
{
    saved.cb = cb;
    saved.data = user_data;
}

static void my_event_cb(const struct event_cb *evt, void *data)
{
    printf("in %s\n", __func__);
    printf("data1: %s\n", (const char *)data);
    printf("data2: %s\n", (const char *)evt->data);
}

int main(void)
{
    char my_custom_data[40] = "Hello!";
    event_cb_register(my_event_cb, my_custom_data);

    saved.cb(&saved, saved.data);

    return 0;
}

Вероятно, необходимо рассмотреть, функционирует ли вызов назад, получает целую структуру event_cb или не - обычно, Вы просто передали бы данные, потому что, как продемонстрировано, иначе у Вас есть два источника той же информации (и запасная копия указателя на функцию, что Вы находитесь в). Существует много очистки, которая может быть сделана на этом - но она действительно работает.


Вопрос в комментариях спрашивает: действительно ли это - хороший пример обратного вызова?

Кратко, нет - но частично потому что нет достаточной инфраструктуры здесь.

В некотором смысле можно думать о функции сравнения, переданной qsort() или bsearch() функции как обратный вызов. Это - указатель на функцию, которая передается в родовую функцию, которая делает то, что родовая функция не может сделать для себя.

Другим примером обратного вызова является функция-обработчик сигнала. Вы говорите системе вызывать свою функцию, когда событие - сигнал - происходит. Вы настраиваете механизмы заранее так, чтобы, когда система должна вызвать функцию, она знала который функция звонить.

Пример кода пытается обеспечить более тщательно продуманный механизм - обратный вызов с контекстом. В C++ это, возможно, было бы функтором.

Часть кода, с которым я работаю, имеет очень суетливые требования об управлении памятью - при использовании в конкретном контексте. Так, для тестирования я использую malloc() и др., но в производстве, я должен установить средства выделения памяти на специализированные средства выделения. Затем я обеспечиваю вызов функции в пакете так, чтобы суетливый код мог переопределить средства выделения памяти по умолчанию со своими собственными суррогатными версиями - и обеспечил работу суррогатов хорошо, код будет вести себя как прежде. Это - форма обратного вызова - снова, форма, которой не нужно много (или ничто) в способе пользовательских данных контекста.

Системы управления окнами имеют обработчики событий (обратные вызовы), которые регистрируются и что GUI, который назовет основной цикл событий, когда события будут иметь место. Им обычно нужен пользовательский контекст, а также определенная для события информация, предоставленная системой GUI.

14
ответ дан 1 December 2019 в 21:12
поделиться

Что предназначено путем "регистрации обратного вызова" и "диспетчера события"?

"регистрация обратного вызова" является действием сообщения, базовой системы, которая точная функция звонить, и (дополнительно) с который параметры, и возможно также, для который конкретный класс событий, что обратный вызов должен быть вызван.

"Диспетчер события" получает события от O/S (или GUI, и т.д.), и на самом деле вызывает обратные вызовы путем взгляда в списке зарегистрированных обратных вызовов для наблюдения, которым интересно в таком случае.

7
ответ дан 1 December 2019 в 21:12
поделиться

Без выхода компилятора это твердо, но я вижу несколько проблем;

int event_cb_register(event_ct_t cb, void *user_data);

Должен быть

int event_cb_register(event_cb_t cb, void *user_data);

my_custom_data переменная не существует, когда она используется здесь;

event_cb_register(my_event_cb, &my_custom_data);

Этот указатель никогда не инициализируется;

struct event_cb *callback;

И в;

callback->cb(event, callback->data);

Вы не можете передать название типа ('событие') к функции, необходимо передать экземпляр того типа.

2
ответ дан 1 December 2019 в 21:12
поделиться

Регистрация обратного вызова означает, что Вы указываете, какая функция должна быть вызвана, когда мероприятие происходит. В основном Вы устанавливаете указатель функции при регистрации обратного вызова.

1
ответ дан 1 December 2019 в 21:12
поделиться
int event_cb_register(event_ct_t cb, void *user_data);

Каков тот тип event_ct_t? Вы имеете в виду event_cb_t?

struct event_cb *callback;

Создает неинициализированный указатель на структуру event_cb. Отметьте главным образом, что это указывает на мусор.

callback->cb(event, callback->data);

Вы пытаетесь назвать мусор. Вам нужна инициализация:

struct event_cb callback;
callback.cb = my_event_cb;
callback.data = 42;

или некоторый такой материал.

2
ответ дан 1 December 2019 в 21:12
поделиться

Вы создали указатель на объявленный вами struct, но он ни на что не указывает:

struct event_cb *callback;

Вам следует просто создать тип вашего struct:

struct event_cb callback;

и затем передать его адрес функциям.

1
ответ дан 1 December 2019 в 21:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: