Навертели всякого…

Начал я тут облагораживать проигрывалку MIDI файлов немножко.

В частности, мне не нравилось, как я сделал реализацию callback-функций, которые вызываются библиотекой. (Сделано было на скорую руку, «чтобы заработало», да так и оставлено.)

И начал я изучать вопрос на тему «есть ли в 2025 году стандартные способы указывать в качестве сишной callback-функции функцию-член класса».

И напоролся на интересную статью, в которой приведён пример (см. рис. 1), который синтактически неправильный для того C++, который я помню. 🙂

Оказывается, пока меня не было, они там в C++ насовали всякого нового (в версию C++ 11). И тот пример из статьи использует это самое новое.

Вот ведь… Придётся разбираться.

Рис. 1

(Да, я в курсе, что C++11 «новый» только для меня, а нормальные программисты уже могут не помнить, что когда-то было как-то иначе.)

Навертели всякого…: 9 комментариев

  1. Мне больше нарвится использование стандартного шаблона std::function который представляет нечто, что может вызываться как функция — это может быть и указатель на функцию, и объект-функция, и лямбда-выражение

    В использовании что то вроде:

    #include
    #include

    void print_num(int i)
    {
    std::cout << i << '\n';
    }

    int main()
    {
    std::function f_display = print_num;
    std::function f_display_42 = []() { print_num(42); };
    std::function f_display_31337 = std::bind(print_num, 31337);
    f_display(-9);
    f_display_42();
    f_display_31337()
    }

    Вывод
    -9
    42
    31337

    1. А если callback должен принимать указатель на данные?

      void my_callback(char * my_data);

      как вызвать член класса, который этот указатель примет?

      (Эти все штуки тоже появились после того, как я «на минуточку отошел» от программирования, поэтому спрашиваю.)

      1. Вот таким образом, главное правильно забиндить функцию

        #include "iostream"
        #include "functional"
        #include "stdio.h"

        struct Foo
        {
        void print(char * buff) {
        // что то делаем
        printf("%s", buff);
        }
        };

        int main() {
        char buff[] = "Какие то данные ";
        //в Си массив это и так указатель можно без этого
        char * buff_ptr = buff;

        //обьявление экземпляра класса
        const Foo foo;

        // просто чтобы в bind вместо std::placeholders::_1 писать просто _1
        using std::placeholders::_1;

        // биндим функцию конкретного экземпляра класса
        // Первый параметр функция которую биндим,
        // вторая экземпляр класса функция которого будет вызываться (или ссылка на него)
        // третий и далее параметры которые будем передавать функции
        // можно как передавать параметры создаваемой функции так и статически заданные значения
        // параметры функции f_display2 которую мы создаем будут называться _1, _2 и.т.д.
        std::function f_display2 = std::bind(&Foo::print, foo, _1);

        f_display2(buff_ptr);

        return 0;
        }

          1. Доброе утро.
            А какой метод крепления плат датчиков на деку в результате оказался лучшим: на термоклей или на герметик?
            А то мне платы для «активной» клавиатуры тоже придётся на деку устанавливать. Пока склоняюсь к варианту термоклея, т.к. не исключено что первый вариант плат потребует доработки и их надо будет снять. С термоклеем хотя бы понятно, как это можно будет сделать.

Добавить комментарий