У меня есть небольшая проблема с использованием библиотеки 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: 🙂 вместо (*). Таким образом, проблема ясна, но, к сожалению, я недостаточно квалифицирован, чтобы ее решить. Я занимаюсь с ++ только в приватное время, и я не настолько глубоко разбираюсь в обратных вызовах, типах и областях. Не могли бы вы, люди, помочь мне найти рабочее решение без публичных методов?
Заранее спасибо!
фатальный
У меня была такая же ошибка. Я также новичок в C ++.
В C ++ существует большая разница между указателями на функции и указателями на функции-члены. Эти ответы мне очень помогли:
Передача функции-члена в качестве аргумента конструктору
C ++ передача функции-члена в качестве аргумента
Как я могу передать функцию-член класса в качестве обратного вызова
Поэтому либо используйте функцию-член с помощью перечисленных ответов, либо используйте статические функции-члены, либо просто используйте простые старые функции, которые не относятся к классу.
Других решений пока нет …