| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Си callback и экземпляр класса |
| Автор: Cheloveck 27.11.2009, 14:03 | ||||||
| Извиняюсь за банальную тему, но полазив по интернетам ничего толкового не нашёл. Итак. Есть закрытая библиотека на Си, одна из функций которой возвращает результат своей деятельности в колбек. У меня в программе её вызывает, естественно, метод класса. Задача - получить данные в конкретный экземпляр. В Сети самый распространённый вариант - использование статических методов в качестве колбека, но тогда нет доступа к членам конкретного объекта. Теперь на примере. Допустим мы имеем потенциальную библиотеку с таким вот кодом
Функция принимает указатель на функцию и вызывает её с неким параметром, который и нужно получить конечному объекту. В нашей программе имеется некий класс
Для наглядности показываем сообщение. Часть данных берётся из конкретного объекта, часть из параметра колбека. Используется примерно так
В итоге должно быть два месаджбокса с текстом "Hello" и заголовками "i'm first" и "i'm second". Хорошо бы найти унивирсальное решение как для stdcall так и для cdecl колбеков. В случае с с stdcall нужно только добавить в ecx указатель this, а в cdecl ещё и перекопировать параметры. Может уже есть готовые решения, что-то не очень горю желанием писать ассемблерные вставки? |
| Автор: SenkraD 27.11.2009, 14:42 | ||
Cheloveck, можно попробовать boost::function (boost::bind):
Добавлено через 9 минут и 6 секунд Звиняюсь, ошибся - нету оператора приведения к поинтеру на функу -> мое решение не верно Добавлено через 14 минут и 24 секунды вот нашёл ещё http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Generalizing_C-Style_Callbacks |
| Автор: djamshud 27.11.2009, 15:25 | ||||||||||||
| Я бы сделал это так (типы немного поменял, но суть сохранилась): Закрытая библиотека:
Сласс
Подготовка к колбекам:
Вызов функции с колбеком:
Результат:
|
| Автор: Cheloveck 27.11.2009, 15:56 |
| djamshud, решение для одного потока более или менее подходит, но при появлении второго всё станет печально. SenkraD, пока не увидел решения этой проблемы, но я ещё поизучаю эту тему. |
| Автор: djamshud 27.11.2009, 16:22 |
| >решение для одного потока более или менее подходит, но при появлении второго всё станет печально. Да, это вполне очевидно. Для потокобезопасного решения нужно организовывать очередь из пар объект-колбек.и запускать в отдельном потоке обработчик этой очереди. Хотя это уже попахивает извращением, да еще и функции, работающие с колбеками, не всегда получится выполнить в другом потоке.. Если время выполнения функции и колбеков невелико, можно просто закрыть мутеком операции присваивания global_object и вызова функции. Когда-то я делал именно так. Там еще была рюшечка в виде произвольного типа класса (т.е. не привязывался непосредственно к Class). Если интересует, могу поискать. В обоих случаях пользоваться будет менее удобно, но в общем терпимо. Сам когда-то мучался с этой проблемой, но найти ничего не получилось и сам додумался только до того, до чего додумался. Возлагал надежды на шаблоны, но не получилось. |
| Автор: null56 27.11.2009, 16:40 | ||
Ну если закрыть глаза на треадсейфность... то колбек метода класса можно вызвать так.... (я приведу рабочий свой пример)
я надеюсь, что я правильно понял вопрос... вызов метода определенного объекта через колбак... внутри метода first я могу пользоваться как данными самого объекта (в данном случае this), так и переданный параметр строку |
| Автор: null56 27.11.2009, 17:08 |
| иными словами, чтобы вызвать колбек метода, нужен сам объект + адрес на метод... в моем примере я делаю это через this, так как вызываю колбек будучи в метода самого объекта... но тоже самое можно сделать и вне методов объета |
| Автор: djamshud 27.11.2009, 17:13 |
| Вы неправильно поняли). Посмотрите первое сообщение топика, а точнее первый кусок "Код С++". Указатель на метод туда никак не впихнуть. |
| Автор: Cheloveck 27.11.2009, 20:31 |
| В общем-то посоветовавшись с людьми я пришёл к выводу, что единственного способа не придумать. Поэтому каждый раз нужно изобретать метод для конкретного случая. Эта тема всплыла у меня на этот раз из-за SQLite, но к нему я нашёл C++ враппер. Посмотрю ещё как он работает (быстро проглядел - там boost), если найду что-то интересное - отпишусь сюда. Всем спасибо, но вопрос по ходу не решаемый (во всяком случае без ассемблера). |
| Автор: Abyx 27.11.2009, 21:16 |
| Cheloveck, при чем тут ассемблер? |
| Автор: Abyx 27.11.2009, 21:31 | ||
| если в коллбек передается какое-то значение которое можно использовать как ключ - делать карту объектов, например для оконной функции - map<HWND, YourClass> если объект 1 на поток, надо использовать TLS, - фактически id потока - ключ для выбора объекта если в коллбек прямо или косвенно не передается никаких значений, позволяющих выбрать нужный объект, то надо создавать уникальные коллбеки либо статически, фиксированное количество - сделать карту<функция,объект>
либо динамически, но это непереносимо, т.к. асм |
| Автор: Cheloveck 27.11.2009, 21:58 |
Я говорил об универсальном способе, а таких "если" уже много было... |
| Автор: Abyx 27.11.2009, 22:00 |
| Cheloveck, тогда тебе нужна универсальная программа %) Добавлено через 2 минуты и 27 секунд наиболее универсальный метод - динамически создавать коллбеки, но это привязывает к архитектуре проца и системному АПИ управления свойствами памяти |
| Автор: Cheloveck 27.11.2009, 22:05 |
| Abyx, ничего универсального. Если выделять память и записывать туда то, что требуется для вызова (я об этом говорил в первом посте) и передавать эту область в функцию вместо колбека - то всё будет замечательно. Так работают оконные колбеки в делфях. Но я не хочу асм |