Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > как сделать CALLBACK-функцию членом класса?


Автор: black_priest 13.12.2007, 16:36
Есть такая функция
Код

MMRESULT waveInOpen(
  LPHWAVEIN       phwi,      
  UINT_PTR       uDeviceID,  
  LPWAVEFORMATEX pwfx,       
  DWORD_PTR      dwCallback, 
  DWORD_PTR      dwCallbackInstance, 
  DWORD          fdwOpen     
);

и есть метод класса
Код

void CALLBACK VJSoundIn::DataBufferReady(HWAVEIN hWaveIn, UINT uMsg,
                                          DWORD dwInstance,
                                          DWORD dwParam1,
                                          DWORD dwParam2);

Как передать параметру dwCallback функции указатель на метод класса VJSoundIn ?   smile 

Автор: BorisVorontsov 13.12.2007, 19:01
Сделай функцию статической

Автор: black_priest 13.12.2007, 21:28
Спасибо, уже сделал, действительно помогает (во всяком случае скомпилировалось smile. Видимо на этапе компиляции линкеру нужен адрес этой функции, поэтму и static.

Сразу возник попутный вопрос.
В определении класса (VJSoundIn.h):
Код
 static void CALLBACK VJSoundIn::DataBufferReady(HWAVEIN hWaveIn, UINT uMsg,
                                          DWORD dwInstance,
                                          DWORD dwParam1,
                                          DWORD dwParam2);

В определнии метода класса (VJSoundIn.cpp)
Код

static void CALLBACK VJSoundIn::DataBufferReady(HWAVEIN hWaveIn, UINT uMsg,  
                                          DWORD dwInstance,
                                          DWORD dwParam1,
                                          DWORD dwParam2)
{
     // тело функции
}


При компиляции дает ошибку error C2724: 'VJSoundIn::DataBufferReady' : 'static' should not be used on member functions defined at file scope
Если определить метод без слова static, т.е. так 
Код

void CALLBACK VJSoundIn::DataBufferReady(HWAVEIN hWaveIn, UINT uMsg,  
                                          DWORD dwInstance,
                                          DWORD dwParam1,
                                          DWORD dwParam2)
{
     // тело функции
}

то компилируется без ошибок. Поясните пожалуйста, почему? (строку перевел, смысл все равно не понятен)


Автор: BorisVorontsov 14.12.2007, 10:11
Цитата(black_priest @  13.12.2007,  21:28 Найти цитируемый пост)
Поясните пожалуйста, почему?


Потому что обозвав функцию статической в файле реализации ты запретил её видимость для других модулей. Решение, как ты заметил, не обзывать её статической.

Автор: black_priest 14.12.2007, 12:32
Смутило просто то, что в одном месте надо писать, а в другом уже не надо. Ведь по логике должно быть так, что ты посмотрел на функцию и можешь понять что она в общем из себя представляет, а так получается информацию о том, что функция статическая можно получить только из заголовочного файла.
А CALLBACK, зараза, все равно не заработал. Есть серьезные подозрения, что причина в том, что приложение консольное. Может есть какие то тонкости при использовании CALLBACK механизмов в консольных приложениях?
BorisVorontsov, спасибо за поддержку  smile  

Автор: Coocky 14.12.2007, 13:37
Цитата(black_priest @  14.12.2007,  12:32 Найти цитируемый пост)
 Есть серьезные подозрения, что причина в том, что приложение консольное. Может есть какие то тонкости при использовании CALLBACK механизмов в консольных приложениях?


Смотрим
 
Код

#define CALLBACK    __stdcall

Есть серьезные предположение,что функцию нельзя импортировать в консольных придожениях? smile

Автор: Coocky 14.12.2007, 13:58
Т.е. выразился неправильно smile Не импортировать, а вызывать На самом деле,как я показал- #define CALLBACK    __stdcall
    __stdcall это convention-т.е согласование о вызове функции. 99% АПИ функций -  __stdcall
Т.е. параметры передаются справа на лево для стека и т.д и т.п. А то,что ты передаешь имя функции,так жто для того,что б вызвать в дебрях той функции,в которую ты передаешь твою калбек. Так что никакого механизма особого нет smile Просто твоя фнкция вызовется через указатель на нее smile И от типа приложения это не  зависит.Никак smile

Автор: black_priest 14.12.2007, 14:43
Спасиб ребята, все заработало. Все таки моя ошибка была по невнимательности, когда waveInOpen делал, параметры попутал. Так что никаких проблем с  __stdcall действительно нет. 
Единственно теперь то, что смущает это фраза из MSDN  в описании wsweInProc:
Цитата

Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock.

Поэтому решил все-таки общаться с драйвером путем сообщений, т.е. вместо вызова CALLBACK функции, настроится на прием сообщений (что в принципе работало в моей программе с GUI, написанной ранее на дельфи). Но возникает сложность, как можно принимать сообщения, если приложение консольное, т.е. не имеет окна, и соотв. оконной процедуры. Погуглив немного этот вопрос, нашел, что часто рекомендуют создавать невидимые message only окна и работать с ними. Мне это решение как-то не очень понравилось. Может есть что-то другое?

Автор: Coocky 15.12.2007, 22:53
black_priest, общаться через сообщения рекомендую только в СВОИХ окнах.Всякие невидимые окна,броадкасты и прочие "костыли" не привествую.
Предлагаю обыкновенное межпроцессорное взаимодействие
1.Pipe хорошая штука.Но есть свои нюансы.Отложим
2.Обьекты синхронизации+ FileMapping /Хорошая вещь.Я через сервис общался со своим приложением smile Даже написал  "сэмулировал" свои сообщения и их обработку.
Рекомендую smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)