Си Callback и Си++ класс

Тема в разделе "LANGS.C", создана пользователем Rel, 5 фев 2011.

  1. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    может баян и проблема тупа, но у меня чет не получилось нагуглить... есть класс, который реализует цпп-интерфейс над си-библиотекой FMOD... в си-библиотеке есть функция, которая загружает файл в память, декодирует его в wav и по завершении этого действа дергает калбек... в классе есть флажок (среди private членов), который должен быть выставлен в true, когда загрузка файла завершилась... калбек должен быть строго определенного вида... поэтому я не могу его сделать методом класса, так как никак не смогу неявно передать указатель this... если я делаю калбек friend функцией, то опять же, как калбек узнает члены какого именно экземпляра нужно менять, как передать указатель this не понятно... глобальной переменной так же не передашь, так как во-первых таких классов одновременно грузящих файлы может быть много, а во-вторых это какое-то коленное решение... что подскажите?)
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Rel

    Колбег случаем не принимает юзердату void* ?
     
  3. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Rel
    когда происходит вызов по передаваемым параметрам можно понять какому экземпляру принадлежит вызов? если да то сделать соответствие эти данные/указатель на класс.
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    к сожалению нет... тогда бы проблем не было...

    ну это как-то сложно... так как надо где-то хранить список всех экземпляров и проходить по нему... в классовою иерархию, которую я планировал не очень вкладывается... но как вариант...
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Если экземпляров много, то массив функций. Каждая функция соответствует определённому экземпляру. Ну а если экземпляр один, то проблемы нет вовсе.
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    ну это как то странно слышится... экземпляров может быть от нескольких до нескольких десятков... все определяется в динамике... можно канещ дублировать функцию из секции кода куда-нить на выделенную страницу, подменять в функции константу указывающую на экземпляр и подставлять в адрес... но это слишком хакерское решение)
     
  7. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Rel
    нормальное решение, всего одни std::map, который статиком в этом же классе лежит, и все. Это не то что сложно, это тривиально. Это самый не хакерный способ, имхо.

    не как не влияет, все внутри класса, прозрачно по отношению к другим классам, наследование конечно может усложнить.
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Rel
    Ну а что тут ещё можно придумать? Да хакерское. ^)
     
  9. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Rel
    Чтобы оно не было очень хакерским, объяви макрос и фигачь определённое кол-во функций, если будет мало - фигачь ещё. ^)
     
  10. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    а, статиком... ясно... ну видимо больше вариантов то и нет...

    ))

    макросом не обойтись... тут динамическое количество, при компиляции не известное... а в статике расплодить n-ное количество функций - это будет слишком много кода имхо)
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Rel
    Нормально решение, но если есть конечно какой-то другой признак, то конечно лучше сделать по-другому.

    Не бесконечное же. А несколько десятков маленьких функций, это ничто.
     
  12. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    ну лан... спасибо всем, кто ответил... если больше вариантов не назовут, сделаю через std::map...
     
  13. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Booster
    да так то нормально, но придется динамично создавать новые функции ( как признак можно использовать ее адрес), а вот как их создавать это вопрос, тут будет явный хак не переносимый. С другим признаком как уже я сказал решение достаточно простое, и переносимое.
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    spa
    Опять же если у нас признак только адрес, то иначе никак не сделаешь. Динамично и не надо создавать, так как предел экземпляров как правило всё равно есть, этот предел и можно макросом зафигачить.
     
  15. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Booster
    согласен
     
  16. wf_

    wf_ New Member

    Публикаций:
    0
    Регистрация:
    18 окт 2009
    Сообщения:
    40
    spa верно говорит про статик, много где видел подобный код.
     
  17. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    2Rel хак пойдет ?
    //rsdn.ru
    Код (Text):
    1. #include <windows.h>
    2.  
    3. #pragma pack(push,1)
    4. struct _ProcThunk
    5. {
    6.    DWORD   m_mov;          
    7.    DWORD   m_this;          
    8.    BYTE    m_jmp;          
    9.    DWORD   m_relproc;      
    10. };
    11. #pragma pack(pop)
    12.  
    13. class ProcThunk
    14. {
    15. public:
    16.    union
    17.    {
    18.       _ProcThunk thunk;
    19.    };
    20.    void Init(void* proc, void* pThis)
    21.    {
    22.       thunk.m_mov = 0x042444C7;
    23.       thunk.m_this = (DWORD)pThis;
    24.       thunk.m_jmp = 0xe9;
    25.       thunk.m_relproc = (int)proc - ((int)this+sizeof(_ProcThunk));
    26.       FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
    27.    }
    28. };
    29.  
    30. __declspec (naked) void* _cdecl pvoid_cast(...)
    31. {
    32.    _asm
    33.    {
    34.       mov eax, [esp+4]
    35.       ret
    36.    }
    37. }
    38.  
    39. class Thread
    40. {
    41.    ProcThunk thunk_;
    42. public:
    43.    DWORD Worker(void* p)
    44.    {
    45.       ::MessageBox("Thread", "Thread", 0, 0);
    46.       return 0;
    47.    }
    48.  
    49.    Thread()
    50.    {
    51.       thunk_.Init(pvoid_cast(Worker), (void*)this);
    52.    }
    53.    
    54.    operator LPTHREAD_START_ROUTINE()
    55.    {
    56.       return (LPTHREAD_START_ROUTINE)&(thunk_.thunk);
    57.    }
    58. };
    59.  
    60. int main(int argc, char* argv[])
    61. {
    62.    Thread t;
    63.  
    64.    HANDLE hThread = CreateThread(NULL, 0, t, NULL, 0, 0 );
    65.    
    66.    WaitForSingleObject(hThread, INFINITE);
    67.  
    68.    return 0;
    69. }
    каллбек будет обычный метод а this будет на инстанс указывать
     
  18. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    osox
    это жесть)
     
  19. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Rel
    Есть библиотечка sigc++ созданная специально для того, чтобы использовать методы классов как C-коллбеки.
     
  20. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    ну может и пойдет, но грязноват он...

    ну вообще, если думать о сигналах... я пока еще не решил, какую гую буду использовать для этого проекта... либо gtkmm, либо qt, а может даже wxwidgets... в библиотеках есть свои методы работы с сигналами (а в gtkmm наверное и используется sigc++)... еще не думал, понадобится ли буст (в нем тоже вроде сигналы есть)... сигналы наверное хороший вариант...