У меня есть обратный вызов с этой подписью (я использую Live555):
typedef void(RTSPClient::responseHandler)(RTSPClient*, ...); //... = other parameters
Затем в моем коде я создал подкласс RTSPClient, следуя правилам библиотеки:
class MyRTSPClient: public RTSPClient {
...
//callback
void continueAfterDESCRIBE(RTSPClient *client, ...); //same signature of typedef
...
};
Теперь проблема.
В моем коде я должен вызвать следующий метод:
unsigned RTSPClient::sendDescribeCommand(responseHandler, ...); //response handler is the typedef
Если я создам объект:
MyRTSPClient *client = MyRTSPClient::createNew(...); //is library requirement such creation
как передать объект функции sendDescribeCommand
качестве обратного вызова?
Конечно, если я объявляю continueAfterDESCRIBE
как статический член, у меня нет никаких проблем, но я хочу объект, потому что у меня много потоков, и если я использую статический callback, вызванный из них, многие проблемы синхронизации будут подняты.
Поэтому я борюсь (как новичок в C++), как узнать правильную подпись, чтобы передать obj->method
в качестве обратного вызова.
Вы не можете использовать нестационарную функцию-член как параметр обратного вызова, который ожидает регулярную функцию, потому что их подписи несовместимы:
Общим решением для этого является возможность, только если библиотека, которая выполняет обратный вызов, позволяет передавать пользовательские параметры с регистрацией обратного вызова. Обычно это делается с помощью указателя void*
, который вы передаете библиотеке при регистрации обратного вызова, а затем библиотека передает ее обратно, когда она вызывает обратную функцию.
Вот как это сделать:
// This is the static function that you register for your callback
static void staticContinueAfterDESCRIBE(RTSPClient *client, ...) {
static_cast<MyRTSPClient*>(client)-> continueAfterDESCRIBE(client, ...);
}
Теперь, когда функция статична, у вас нет проблем с ее регистрацией в качестве обратного вызова. Как только функция получает элемент управления, он MyRTSPClient*
client
в ваш класс MyRTSPClient*
и выполняет нестатический обратный вызов.
Вам нужны два указателя: один для объекта и один для функции-члена:
void (RTSPClient::*mfptr) = &RTSPClient::continueAfterDESCRIBE;
и один к объекту:
RTSPClient* p = new RTSPClient();
а затем назовите его:
p->*mfptr(...);
client
передается обратно библиотекой, управление потоками также контролируется библиотекой: если у каждого потока есть собственныйclient
, синхронизация не требуется. Если несколько потоков могут использовать один и тот жеclient
, вам необходимо выполнить синхронизацию. В любом случае вам нужно будет синхронизироватьcontinueAfterDESCRIBE
, а неstaticContinueAfterDESCRIBE
, поскольку статическая оболочка никогда не обращается к каким-либо общим ресурсам явно.