С++ обратный вызов BASS после завершения внутреннего класса

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

Foo.h:

class Foo
{
    public:
        Foo(void);
        ~Foo(void);
        void endOfFile(void);
    private:
        HSTREAM _streamHandle;
        void playFile(string);
};

Foo.cpp:

void Foo::playFile(string fileName)
{
    _streamHandle = BASS_StreamCreateFile(false, fileName.c_str(), 0, 0, BASS_STREAM_AUTOFREE);
    BASS_ChannelSetSync(_streamHandle, BASS_SYNC_END, 0, endOfFileCallback, this);
    BASS_ChannelPlay(_streamHandle, true);

void Foo::endOfFile()
{
    playFile(getNextFileFromSomewhere()); // obviously this is done different in production code
}

void CALLBACK endOfFileCallback(HSYNC handle, DWORD channel, DWORD data, void* pTarget)
{
    Foo* pFoo = static_cast<Foo*>(pTarget);
    pFoo->endOfFile();
}

Итак, это работает, но выглядит уродливо, имея функцию, а не метод, вызываемый как обратный вызов, и оппонировать endOfFile как общедоступный метод. Это должно быть частным. Поэтому я попытался использовать метод в качестве обратного вызова...

Bar.h:

class Bar
{
    public:
        Bar(void);
        ~Bar(void);
    private:
        HSTREAM _streamHandle;
        void playFile(string);
        void endOfFile(void);
        void CALLBACK endOfFileCallback(HSYNC, DWORD, DWORD, void*); // now declaration in class
};

Bar.cpp:

void Bar::playFile(string fileName)
{
    _streamHandle = BASS_StreamCreateFile(false, fileName.c_str(), 0, 0, BASS_STREAM_AUTOFREE);
    BASS_ChannelSetSync(_streamHandle, BASS_SYNC_END, 0, endOfFileCallback, 0); // no reference to 'this' needed
    BASS_ChannelPlay(_streamHandle, true);

void Bar::endOfFile()
{
    playFile(getNextFileFromSomewhere()); // obviously this is done different in production code
}

void CALLBACK Bar::endOfFileCallback(HSYNC handle, DWORD channel, DWORD data, void* pTarget)
{
    endOfFile();
}

Но это не компилируется :-(

error: cannot convert 
    ‘Bar::endOfFileCallback’ 
from type 
    ‘void (Bar::)(HSYNC, DWORD, DWORD, void*) {aka void (**Player**::)(unsigned int, unsigned int, unsigned int, void*)}’ 
to type 
    ‘void (*)(HSYNC, DWORD, DWORD, void*) {aka void (*)(unsigned int, unsigned int, unsigned int, void*)}’

Я думаю, вы видите разницу (Bar::) вместо (*). Итак, проблема ясна, но, к сожалению, у меня недостаточно навыков, чтобы решить ее. Я занимаюсь С++ только в личное время, и я не так глубоко разбираюсь в обратных вызовах, типах и областях. Можете ли вы помочь мне найти рабочее решение без общедоступных методов?

Заранее спасибо!

Фатальный


person FatalDiskError    schedule 09.01.2016    source источник


Ответы (1)


У меня была такая же ошибка. Я также новичок в C++.

В C++ существует большая разница между указателями на функции и указателями на функции-члены. Эти ответы мне очень помогли:

Передача функции-члена в качестве аргумента конструктору

С++ передает функцию-член в качестве аргумента

Как я могу передать функцию-член класса как обратный вызов

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

person vuko_zrno    schedule 18.04.2016