Передать объект класса C ++ в лямбда-захват и преобразовать его в пустой указатель для передачи в C API - PullRequest
0 голосов
/ 08 апреля 2020

Я новичок в функциональной библиотеке. Я хочу передать лямбду в функцию, которая в конечном итоге преобразует это std::function<void()> в пустой указатель. Мне нужно передать эту функцию void в C API. Эта лямбда также принимает текущий объект класса в качестве захвата. Вот фрагмент кода. Любая помощь приветствуется:

class Animal{
    public:
        Animal(std::function<void()> func){}

        // call C API that takes in void(*)()
        call_c_api(func); // Somehow convert func to void *
};
class Cat{
    private:
        std::string m_name;
        Animal m_animal;
    public:
        static StaticCatFunc(Cat*instance){
               std::cout << "Name: " << instance->m_name <<"\n";
        }
        Cat(){
           m_animal = new Animal([this](){StaticCatFunc(this);})
        }
};

Мне нужно для достижения вышеуказанной функциональности. Это не вопрос наследства. Мне нужно как-то конвертировать лямбда с захватом в пустой указатель. Я читал, что лямбды с захватом не могут быть преобразованы в необработанные указатели. Есть ли способ достичь этой функциональности? Любая помощь приветствуется.

=========== Обновление =========

c API выглядит следующим образом:

call_c_api(void (*handler)());

1 Ответ

0 голосов
/ 08 апреля 2020

Вы не можете сделать это, так как std::function захват достигается посредством стирания типа. Он не может быть преобразован в указатель на функцию C, если у него нет захваченных аргументов. Чтобы это работало, вам нужно использовать вызовы C в стиле обратного вызова.

// In a C header
void c_api(void(*callback)(void*), void* userdata);

// In a C++ header
struct MyStruct {
    MyStruct(std::function<void()> func) {
        _func = std::move(func);
        c_api(&MyStruct::CallbackFromC, this);
    }

    static void CallbackFromC(void* data) {
        MyStruct* self = reinterpret_cast<MyStruct*>(data);
        self->_func();
    }

    std::function<void()> _func;
};

Важно отметить, что MyStruct MUST по-прежнему может быть действительным указателем при вызове обратного вызова , или вы получите SEGFAULT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...