При передаче ссылок на объекты C ++ в код на C обычно лучше передавать непрозрачный указатель на динамически размещаемый объект.Это, как правило, создается new
.В этом случае вы можете использовать new
с конструктором перемещения T
, чтобы получить указатель на динамически размещенный объект, не принадлежащий ни одному объекту C ++ RAII.Затем вы можете сохранить копию этого указателя в очереди FreeRTOS.
bool sendToBack(T &&item) {
T *item_ptr = new T(std::move(item));
if (xQueueSendToBack(this->frtosQueueHandle, &item_ptr, portMAX_DELAY) != pdTRUE) {
delete item_ptr;
return false;
}
return true;
}
Обратите внимание, что вместо item_ptr
берется адрес item_ptr
, как xQueueSendToBack()
's * 1010Аргумент * - это указатель на данные для копирования в очередь, а необработанные байты самого указателя - это то, что должно храниться в очереди.Это также означает, что при создании очереди вы должны передать sizeof(T *)
как uxItemSize
при вызове uxQueueCreate()
.
Я бы порекомендовал изменить sendToBack
, чтобы также поддерживать копирование и переход к переключению напереадресация ссылки следующим образом:
template<typename ItemT>
bool sendToBack(ItemT &&item) {
T *item_ptr = new T(std::forward<ItemT>(item));
if (xQueueSendToBack(this->frtosQueueHandle, &item_ptr, portMAX_DELAY) != pdTRUE) {
delete item_ptr;
return false;
}
return true;
}
Наконец, чтобы получить элемент из очереди, это можно сделать следующим образом:
T receive() {
T *item_ptr;
xQueueReceive(this->frtosQueueHandle, &item_ptr, portMAX_DELAY);
// Copy / move the item out of the dynamically allocated object and
// into a local object.
T item(std::move(*item_ptr));
// The original object is moved-from but still must be deleted.
delete item_ptr;
return item;
}
Это можно сделать несколько более надежным и безопасным для исключений.если T
не имеет noexcept
конструктора перемещения / копирования путем немедленной передачи права собственности unique_ptr
следующим образом:
T receive() {
T *item_ptr;
xQueueReceive(this->frtosQueueHandle, &item_ptr, portMAX_DELAY);
std::unique_ptr<T> item_unique_ptr(item_ptr);
T item(std::move(*item_ptr));
return item;
}
Также очень важно, чтобы вы вручную просматривали элементы в своей очереди иудалите все оставшиеся элементы в деструкторе FreeRtosQueue
, так как в противном случае сохраненные указатели на динамически распределенную память неуправляемы.Вам также следует отключить конструктор копирования класса (и при необходимости реализовать конструктор перемещения).