Основной подход - хранить где-то копию callback
, а затем передать указатель на нее как pApplicationHandlerData
.
Примерно так:
extern "C"
void application_handler_forwarder(
AWS_IoT_Client *pClient,
char *pTopicName,
uint16_t topicNameLen,
IoT_Publish_Message_Params *pParams,
void *pClientData
) {
auto callback_ptr = static_cast<std::function<void(const std::string&)> *>(pClientData);
std::string topic(pTopicName, topicNameLen);
(*callback_ptr)(topic);
}
Это ваша(C-совместимый) универсальная функция-обработчик, которая просто пересылает std::function
, на который ссылается pClientData
.
. Вы бы зарегистрировали его в subscribe
как
void AWS::subscribe(const std::string &topic, std::function<void(const std::string&)> callback) {
...
aws_iot_mqtt_subscribe(pClient, topic.data(), topic.size(), qos,
application_handler_forwarder, ©_of_callback);
, где copy_of_callback
std::function<const std::string &)>
.
Единственная сложная часть - управление временем жизни объекта обратного вызова.Вы должны сделать это вручную в части C ++, потому что она должна оставаться в живых до тех пор, пока подписка действительна, потому что application_handler_forwarder
будет вызываться с ее адресом.
Вы не можете просто передать указатель напараметр (&callback
), поскольку параметр является локальной переменной, которая уничтожается при возврате функции.Я не знаю вашу библиотеку C, поэтому не могу сказать вам, когда можно безопасно удалить копию обратного вызова.
Примечание: очевидно, вам нужно extern "C"
для обратного вызова, даже еслиего имя никогда не просматривается кодом C, поскольку оно не только влияет на искажение имени, но также гарантирует, что код использует соглашение о вызовах, ожидаемое C .