LINUX.ORG.RU

С++. Callback функция


0

0

Всем привет,

Хочу реализовать примерно следующее: класс Parser, который содержит объект Socket. Socket запускает thread и при приёме данных вызывает метод в Parser и передаёт ему принятые данные.
Вопрос примерно следующий: можно ли это как-то реализовать в C++, не объявляя эту Callback функцию в Parser как static?

Всем спасибо
Velik



Последнее исправление: velikS (всего исправлений: 1)

Сессия?
Два вопроса:
1. Что ты делал последние полгода?
2. Кем собираешься работать в будущем?

Love5an
()

Используй вместо callback-а класс с перегруженным operator (). В C++ указатели на функции (почти) не нужны.

one_more_hokum ★★★
()

>можно ли это как-то реализовать в C++, не объявляя эту Callback функцию в Parser как static?

Можно

yoghurt ★★★★★
()
Ответ на: комментарий от Love5an

Нет, не сессия - насущные проблемы.
1. Много чего делал. Что конкретно интересует?
2. Тем же, кем и в последнее время - архитектором и разработчиком в embedded.

Есть что по делу сказать, или зашёл писькой померяться?

velikS
() автор топика
Ответ на: комментарий от one_more_hokum

Спасибо за линк, а то предыдущее сообщение от вас не понял. посмотрю.

velikS
() автор топика
Ответ на: комментарий от catap

я закончил 2 универа, один из них в Германии. 12 лет в embedded. Живу, работаю в Мюнхене. Не стесняюсь задавать дурацкие вопросы, если чего не понимаю. Не пишу херни, когда нечего сказать по делу.

velikS
() автор топика

Используйте абстрактные классы. Например так:

class ParserInterface {
public:
virtual void someCallback(void) = 0;
}

class Socket {
private:
ParserInterface *parser;

public:
Socket(ParserInterface *_parser){
this->parser = _parser;
}

void startThread (void)
{
// some actions for set up thread
this->parser->someCallback();
}
}

class Parser : public ParserInterface {
private:
Socket *socket;

public:
Parser(){
this->socket = new Socket(this);
}

void someFunction(void){
...
this->socket->startThread();
}

virtual void someCallback(void) {
// implementation of callback function
}

virtual ~Parser(){
delete this->socket;
}
}


http://www.cyberguru.ru/programming/cpp/cpp-language-straustrup3.html

и в частности: http://www.cyberguru.ru/programming/cpp/cpp-language-straustrup3-page35.html

Slavaz ★★★★★
()
Ответ на: комментарий от Slavaz

Опс... недочитал немного. в новом потоке...

В новом потоке разве что передавать указатель на весь класс.

Slavaz ★★★★★
()
Ответ на: комментарий от Slavaz

Спасибо за идею, но такое, как вы сами поняли, работать не будет. Передавать указатель в Socket на весь объект Parser - у меня такая идея была, но ищу что-то другое, поскольку хочется сохранить относительно хорошую структуру. Закончится футбол, почитаю, что one_more_hokum предлагает. Пока наши проигрывают 1/0 :-(

velikS
() автор топика
Ответ на: комментарий от Slavaz

Ты еще многого не дочитал. Он собирается дёргать из агрегированного класса метод агрегирующего.


можно ли это как-то реализовать в C++, не объявляя эту Callback функцию в Parser как static?


Можно, но тебе вообще не нужен коллбэк. Пересмотри проядок вызова функций.

LamerOk ★★★★★
()
Ответ на: комментарий от velikS

>Передавать указатель в Socket на весь объект Parser - у меня такая идея была, но ищу что-то другое, поскольку хочется сохранить относительно хорошую структуру.

1. Передавай туда указатель на объект стратегии CallableFromSocket, от которой будет частично отнаследован и парсер

2. Передавай туда объект-прокси, например, или что-то в этом духе.

yoghurt ★★★★★
()
Ответ на: комментарий от LamerOk

Он собирается дёргать из агрегированного класса метод агрегирующего.


Даже, если разделить эти два объекта и сделать некий третий Receiver, который содержит и Socket, и Parser, то это лишь только улучшит структуру, но не решит проблему.

Можно, но тебе вообще не нужен коллбэк. Пересмотри порядок вызова функций.

Уже пытался пересмотреть, callback нужен. Socket занят стандартной инициализацией и запускает thread c recvfrom. Как только что-то принято, надо это немедленно передать на Parser.

И не хотнлось бы делать один общий класс с сокетом и парсером - у них слишком разные функции

Всем спасибо за дельные ответы

velikS
() автор топика
Ответ на: комментарий от velikS

> Socket занят стандартной инициализацией и запускает thread c recvfrom. Как только что-то принято, надо это немедленно передать на Parser.

Ну и замечательно. Что мешает сокету агрегировать парсер и передавать ему на обработку очередную порцию данных?

Поток ты втиснул куда-то не туда. Либо поток на дескриптор, либо поток на сокет.

У тебя всё как-то кверх ногами...

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Что мешает сокету агрегировать парсер и передавать ему на обработку очередную порцию данных?

Нафига козе баян (С народная мудрость). Сокет - универсальный класс. Парсеров мне надо примерно с десяток. Передавать сокету указатель на весь объект парсер - не слишком элегантное решение.


Поток ты втиснул куда-то не туда. Либо поток на дескриптор, либо поток на сокет.

По сути сокет у меня и крутится в потоке. Есть поток программы и поток приёма по сокету.

velikS
() автор топика
Ответ на: комментарий от velikS

> Передавать сокету указатель на весь объект парсер - не слишком элегантное решение.

На абстрактного предка - вполне себе элегантное.

По сути сокет у меня и крутится в потоке. Есть поток программы и поток приёма по сокету.


Делай нормальную межпотоковую очередь.

LamerOk ★★★★★
()
Ответ на: комментарий от kulti

А, звиняюсь. Не почитал тред. Парсеров много - тут наблюдатель нужен.

kulti ★★
()
Ответ на: комментарий от velikS

архитектором и разработчиком в embedded

12 лет в embedded

как страшно жить. раз ты хочешь передавать туда нестатическую функцию, то тебе нужно какое-то состояние, на которое она замкнута; какое именно состояние тебе нужно? если нужна работа со всем объектом типа Parser - передавай указатель this, если только часть - оборачивай данные в функтор и отправляй его. вообще говоря, мотивацию для того, что ты хочешь сделать, стоило бы написать явно

и, кстати, что это за embedded с C++ внутре, да ещё и в Мюнхене? уж не на харман ли ты работаешь?

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

embedded меняется, господа. Если раньше НУЖНО было писать на асме, потом на С, то сегодня и С++ тут вполне пойдёт. На АРМ9 с 400МГц, какие проблемы запустить линукс. Вот тока последние лет 9 работал ТОЛЬКО с С, потому в голове и каша.

Embedded в одном мед. устройстве. Фирма в Гамбурге. Я живу и работаю в Мюнхене.
Я явно писал, чего хочу: есть универсальный класс сокет с потоком внутри на приём, как только что-то принял - передаёт парсеру. Парсер в класс сокет всовывать - решение через попу. Сокет универсальный класс, парсеров с десяток: т.е. слушаю примерно с десяток сокетов, у каждого свой набор сообщений. Передавать this на парсер в сокет - первое, что мне пришло в голову, ищу другое решение.

velikS
() автор топика
Ответ на: комментарий от velikS

Передавать this — это частный случай того, что делает boost::bind. А boost::function — это реализация того, о чём говорил one_more_hokum.

k_andy ★★★
()
Ответ на: комментарий от LamerOk

Всем ещё раз спасибо за ответы. Как вижу, простого решения в С++ для этого нету, но зато высказанное тут заставило ещё раз пересмотреть, что я делаю. Думаю, что LamerOk прав: я организовал поток не в том месте. Сами мы железячники, привыкли, что всё крутится так сказать снизу - через прерывания и тд. Поэтому сперва и думал сделать одну функцию с бесконечным циклом опроса recvfrom, и эту функцию запустить в отдельном потоке. Как только recvfrom принимает данные - передаю их парсеру. Для этого и нужна была бы CallBack

Но после обсуждения буду делать по-другому: сделаю класс Receiver, в который будут включены мои универсальный Socket и индивидуальный Parser. Запущу в Receivere поток на приём, из потока буду вызывать функцию приёма в Сокете. Если сокет что принял, Receiver передаёт это сам на парсер. С таким решением и обойду Callback функции, которые так любят в С.

Ещё раз всем спасибо за дельные советы
До скорого :)))
Velik

velikS
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.