LittleBuster
@LittleBuster

Указатель на функцию из библиотеки на Си в С++ класс?

Допустим есть Си библиотека такого вида:
struct my_t {
    void (*send_sms)(int);
};

struct my_t *my_new(void)
{
    struct my_t *m;
    m = (struct my_t*)malloc(sizeof(struct my_t));
    return m;
}

void my_test(struct my_t *m)
{
    (*m->send_sms)(545);
}


Вопрос такой: как обрабатывать вызовы указателя на функцию в С++ классе?

Пробовал так:
MainWindow::MainWindow(QWidget *parent)...
{
    my = my_new();
    my->send_sms = this->test;
...


Но компилятор говорит, что функция test должна быть статическим членом класса, а если я её делаю статической, то не могу обрабатывать события из си библиотеки занося их результаты в поля класса окно через this. И всё что мне остаётся, это выводить какойнить MessageBox. Хотел сделать статический сигнал, но компилятор тоже ругается. Мне нужно присваивать результат компонентам окна, как быть?
  • Вопрос задан
  • 606 просмотров
Решения вопроса 1
AxisPod
@AxisPod
Да, не можете. Метод может быть вызван только имея 2 указателя, указатель на объект и указатель на функцию, при этом тип метода содержит в себе тип объекта. Соответственно в C либе вы сможете сохранить только в 2 указателя, но вызвать из C метод вы не сможете.

Но можно сделать что-то типа
// C
struct my_t {
    void (*send_sms)(int);
    void* context;
};

void my_test(struct my_t *m)
{
    (m->send_sms)(545, m->context);
}

// C++
void send_sms_helper(int value, void* context) {
  MainWindow *wnd = reinterpret_cast<MainWindow*>(context);
  wnd->test(value);
}

MainWindow::MainWindow(QWidget *parent)...
{
    my = my_new();
    my->send_sms = send_sms_helper;
    my->context = this;


А send_sms_helper лучше сделать статическим в MainWindow.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Nipheris
@Nipheris Куратор тега C++
Очень просто: чтобы поменьше влиять на остальной код на C++, который у вас уже написан, сделайте следующее:
1) заведите обычную функцию (НЕ член класса) send_sms, указатель на которую отдадите в либу;
2) сделайте в этой функции все, что необходимо по задаче (отправить смс? :));
3) реализуйте для MainWindow синглтон (проще) или сервис (правильнее), чтобы иметь возможность получить доступ из внешней функции send_sms к экземпляру окна;
4) у MainWindow дергайте метод test или любой другой, чтобы передать в него нужные данные. Если сделаете синглтон, будет что-то вроде этого: MainWindow::instance()->test(...);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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