Re: Callback вызов
От: Alex Alexandrov США  
Дата: 02.09.06 05:02
Оценка: 2 (1)
Здравствуйте, LeonCrew, Вы писали:

LC>Коллеги, посоветуйте, как лучше организовать обработку вызова Callback.

LC>Изначально к ПК можно было подключать только одно устройство и в драйверах никто не предусмотрел идентификатор устройства при вызове Callback функции. Фактически, разработчик делал так:
LC>
LC>SetCallback( DeviceId, CallbackFunc );
LC>

LC>Где-то в программе:
LC>
LC>int __stdcall CallbackFunc( const void *Buffer, int Length)
LC>{
LC>….
LC>}
LC>

LC>Теперь же при модернизации устройства стало возможным подключать до 64 таких устройств к одному ПК. Если изначально известно сколько будет устройств подключено или использовано в данной задаче, то вопросов не возникает, но! Поставлена задача написать универсальный класс для работы с любым количеством устройств. Как выполнить данную задачу, если пишется класс с static функцией на которую ссылаются все SetCallback и при этом нет возможности понять, с какова устройства пришел непосредственно вызов.
LC>Править драйвера устройства нет возможности. На данный момент есть мысль: написать обработчик в виде DLL и запускать столько копий DLL сколько устройств.

LC>Платформа Windows, но если есть более универсальный способ – буду только рад.


Может, я что-то не так понял, но тем не менее. Если известно, что устройств не больше, чем 64, то нельзя ли просто написать 64 небольших функции-транслятора и новый SetCallbackEx:


typedef (*NewCallbackFunc)(DeviceId deviceId, const void *Buffer, int Length);

NewCallbackFunc g_callbacks[64] = { 0 };

int SetCallbackEx(DeviceId deviceId, NewCallbackFunc callbackFunc)
{
    switch (deviceId):
    {
    case 0 :
        g_callbacks[0] = callbackFunc;
        return SetCallback(0,  CallbackThunk0);
    case 1:
        g_callbacks[1] = callbackFunc;
        return SetCallback(1,  CallbackThunk1);
    // ...
    case 63:
        g_callbacks[63] = callbackFunc;
        return SetCallback(63,  CallbackThunk63);
    default: return ERROR_WRONG_DEVICE_ID;
    }
}

int __stdcall CallbackThunk0(const void *Buffer, int Length)
{
    assert(g_callbacks[0]);
    g_callbacks[0](0, Buffer, Length);
}

int __stdcall CallbackThunk1(const void *Buffer, int Length)
{
    assert(g_callbacks[1]);
    g_callbacks[1](1, Buffer, Length);
}


Большую часть можно сделать макросами.

P.S. Чтобы избежать новых проблем в будущем, я бы сразу сделал не SetCallback, а AddCallback/RemoveCallback. Для поддержки множества слушателей.
It's kind of fun to do the impossible (Walt Disney)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.