Консультация № 113965
14.12.2007, 11:39
0.00 руб.
0 1 1
Здравствуйте, уважаемые эксперты!
Вопрос в следующем: как сделать так, чтобы callback-функция СИ-шной библиотеки вызывала метод класса-обёртки, причём без каких-либо дополнительных действий со стороны пользователя класса?

Теперь подробнее.
Есть Сишная библиотека BASS и есть желание сделать класс-обёртку в QT4. Всё прекрасно получается кроме одного: не получается сделать callback-функцию, которая-бы вызывала метод этого класса. Пробовал как в приложении - в простейшей тестовой проге работало, в другой перестало, да и сам чую, что неправильно это... Читал интернет - сложные конструкции и требуют написания дополнительных классов и создания их экземпляров в программе, что мне кажется неудобным. Может есть ещё способы?

Приложение:
// classclass QBassPlayer : public QObject{//========================================================================== Q_OBJECTpublic: enum BassState{Closed, Stopped, Playing, Paused, Stalled};public: QBassPlayer(const int Device = -1, const unsigned long SampleRate = 44100, const bool SetMono = false); ~QBassPlayer();//...тыры-пыры... const QBassPlayer::BassState& getState();public slots: bool play(); bool stop(); bool pause();signals: void stateChanged(QBassPlayer::BassState newState);private: BassState currState; uint32_t hStream;};//==========================================================================void QBassPlayer::openFile(const QString& FileName){ if(getState() != Closed) closeFile(); if( (hStream = BASS_StreamCreateFile(false, FileName.toAscii(), 0, 0, BASS_STREAM_PRESCAN)) == 0) throw QString(tr("Невозможно открыть файл: код %1!")).arg(BASS_ErrorGetCode()); if(BASS_ChannelSetSync(hStream, BASS_SYNC_END, 0, (SYNCPROC *)endSyncFn, this) == 0) //бррр.. вот тут я устанавливаю функцию, вызываемую при окончании воспроизведения throw QString(tr("Невозможно установить SYNC: код %1!")).arg(BASS_ErrorGetCode()); getState();}//==========================================================================//ugly hack :-)//воспроизвожу по памяти, поэтому возможны ошибки, но суть понятнаvoid __stdcall endSyncFn(uint32_t handle, uint32_t channel, uint32_t data, uint32_t user){ QBassPlayer *p_pl = (QBassPlayer *)user; // по-моему я делал через reinterpret_cast, а может и нет... if(p_pl) p_pl->getState();}

Обсуждение

Неизвестный
14.12.2007, 13:15
общий
это ответ
Здравствуйте, Сергей Владимирович!

Почему же неправильно? Это должно работать... Ваш код - одна из стандартных ситуаций с передачей указателя на класс с последующим его восстановлением. Например, это используется в билиотеках FLAC, Newton. Да и вообще среди C-библиотек весьма распространённое явление. Можно попробовать сделать Вашу функцию-обработчик закрытым статическим членом в классе. Но это сильно не поможет (кроме открытия доступа к закрытым членам).

Тип функции, который принимает BASS_ChannelSetSync - SYNCPROC*. Это указатель на функцию с определённым числом параметров и определёнными типами. Как же ещё по другому сделать?
Форма ответа