Wskaźnik do funkcji wewnątrz klasy - jak zrobić

0

Witam,
Mam problem ze wskaźnikiem do funkcji. Mam następująca funkcję, używaną przez bibliotekę BASS:

void CALLBACK MySyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
}

Ta metoda jest wywoływana w następujący sposób w kodzie:

BASS_ChannelSetSync(chan, BASS_SYNC_POS, sek_koncowa_bajt, &MySyncProc, 0);

Wtedy wszystko działa.

Tworzony program to aplikacja Qt korzystająca z MainWindow.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtGui>
#include <windows.h>
#include "bass.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private:
    Ui::MainWindow *ui;
    QTimer* timer;
    DWORD chan;
private slots:
    void dodaj();
    void play();
    void stop();
    void update();
};

void CALLBACK MySyncProc(HSYNC, DWORD, DWORD, void*);

#endif // MAINWINDOW_H

W takim układzie wszystko się kompiluje. Chciałbym jednak wskazywaną metodę uczynić częścią mojej klasy (aby ułatwić tworzenie obiektów Qt, na przykład QMessageBox na początek dla testów).

Problem: W jaki sposób wskazać funkcję będącą częścią klasy MainWindow?

Gdy zrobię:

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private:
    void CALLBACK MySyncProc(HSYNC, DWORD, DWORD, void*);
    Ui::MainWindow *ui;
    QTimer* timer;
    DWORD chan;
private slots:
    void dodaj();
    void play();
    void stop();
    void update();
};

W kodzie wygląda to teraz tak:

 BASS_ChannelSetSync(chan, BASS_SYNC_POS, sek_koncowa_bajt, &MainWindow::MySyncProc, 0);

Otrzymany komunikat o błędzie:

mainwindow.cpp:66: błąd:cannot convert 'void (MainWindow::*)(HSYNC, DWORD, DWORD, void*)' to 'void (*)(HSYNC, DWORD, DWORD, void*)' for argument '4' to 'HSYNC BASS_ChannelSetSync(DWORD, DWORD, QWORD, void (*)(HSYNC, DWORD, DWORD, void*), void*)'

Dziękuje za uwagę.

0

zrób funkcję poza klasą, a jeśli potrzebujesz instancji klasy, to podawaj this jako ten ostatni parametr (void *user), czyli:

BASS_ChannelSetSync(chan, BASS_SYNC_POS, sek_koncowa_bajt, &MySyncProc, this);

...

void CALLBACK MySyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
   QMainWindow *window = (QMainWindow*)user;
   ... // tutaj masz okno w zmiennej `window`
}
0

Dzięki za odpowiedź.

Ustawiłem przywoływanie zdarzenia na:

            BASS_ChannelSetSync(chan, BASS_SYNC_POS, sek_koncowa_bajt, &MySyncProc, this);

W tej chwili procedurka poza klasą wygląda tak:

void CALLBACK MySyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
    QMessageBox::information((QWidget*)user, "Wiadomosc", "Tekst");
}

W momencie, gdy zdarzenie jest wykonywane program kończy się:

ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel/qwidget.cpp, line 1299
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.

Zastanawia mnie w jaki sposób można pogodzić to hierarchią obiektów Q_OBJECT?

Gdy jutro wstanę zabieram się za poszukiwanie odpowiedzi.

0

Zamieniłem na:

void CALLBACK MySyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
    QMainWindow *window = (QMainWindow*)user;
    QMessageBox::information(window, "Wiadomosc", "Tekst");
}

Wciąż nie rozwiązuje to problemu, działa dokładnie tak samo.

0

Przecież komunikat piszę o co biega.
Nie możesz cokolwiek robić z okienkiem z innego wątku.
Prawdopodobnie ten callback jest odpalany z innego wątku niż ten typ na który konwertujesz void *user.
Jeżeli musisz wyświetlać tą informacje w imieniu głównej formatki to zrób to w obszarze zsynchronizowanym z wątkiem formatki, np wysyłasz komunikat/sygnał, a wyświetlasz w metodzie odbierającej komunikat/sygnał.

0

Dzięki, trochę mi to rozjaśniło.

Chciabym zrobić tak:

  1. W odpowiednim momencie procedura jest wywoływana (to działa).
  2. W tej metodzie chciałbym wyemitować sygnał, który następnie mogę przechwycić w qApp i tym samy wyświetlić QMessageBox we właściwym wątku.

Pojawia się jednak następujący problem: w jaki sposób wyemitować sygnał z procedury, która nie jest obiektem? Aby emitować sygnały musiałbym utworzyć klasę, która będzie zawierała odpowiednią metodą w częsci signal, a następnie wydać emit. Jednak nie chce to działać dla pojedynczej procedury..

0

OK, to już mi działa. Metoda statyczna klasy MainWindow wywoływana wewnątrz procedury emituje sygnał.

1 użytkowników online, w tym zalogowanych: 0, gości: 1