2015-11-18 5 views
0

Я работаю над приложением C++, чтобы заполнить массив Bluetooth с некоторой информацией. Он основан на mbed platform BLE_API, но я не думаю, что это должно быть актуальным. У меня есть следующий код, который я пытаюсь перефразировать в функцию.Возвращение целого массива нестандартного типа из функции C++

GattAttribute nameDescr1(BLE_UUID_DESCRIPTOR_CHAR_USER_DESC, (uint8_t *)"Percentage", strlen("Percentage")); 
GattAttribute *pdescriptors[] = { &nameDescr1 }; 


    PercentageFill(PercentageUUID, valueBytes.getPointer(), 
        valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 
        GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
        pdescriptors, 
        sizeof(pdescriptors)/sizeof(GattAttribute*)), 

Я до сих пор получил это:

GattAttribute produceName (char title[]) { 
     GattAttribute nameDescr(BLE_UUID_DESCRIPTOR_CHAR_USER_DESC, (uint8_t *)title, strlen(title)); 
     GattAttribute *descriptors[] = { &nameDescr }; 
     return descriptors; 
    } 

Однако, вполне предсказуемо я бросаю ошибку:

Error: No suitable constructor exists to convert from "GattAttribute *[1]" to "GattAttribute"

Я могу понять, почему он бросает, но не являюсь как я должен возвращать весь массив, так как это формат, который требуется в конструкторе «PercentageFill».

Спасибо.

Update:

Чтобы дать полный контекст, вот другие Characteristcis Я настраиваю (каждый с другим именем):

NewService(BLE &_ble, uint8_t percentageFill, uint8_t replacementDue) : 
    ble(_ble), 
    valueBytes(percentageFill), 
    PercentageFill(PercentageUUID, valueBytes.getPointer(), 
        valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 
        GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
        pdescriptors, 
        sizeof(pdescriptors)/sizeof(GattAttribute*)), 
    Time( TimeUUID, 
      &replacementDue, 
      GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
      tdescriptors, 
      sizeof(tdescriptors)/sizeof(GattAttribute*)), 
    UseProfile(UseProfileUUID, 
       &controlPointValue, 
       GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
       Udescriptors, 
       sizeof(Udescriptors)/sizeof(GattAttribute*)),) { 
       setupService(); 
} 
+4

В сообщении об ошибке упоминается «конструктор», который говорит мне, что вы действительно программируете C++. –

+0

Вы уверены, что кодируете в C? Сообщение об ошибке больше похоже на компилятор C++. В C (и, AFAICR, в C++ тоже) вы не можете вернуть массив из функции. Вы можете вернуть указатель (но вы не можете позволить себе вернуть указатель на локальную переменную). Вы можете вернуть структуру, содержащую массив. Но вы не можете вернуть массив напрямую. –

+0

Да, компилятор - это C/C++, поэтому он, вероятно, является C++, в прошлый раз, когда я пометил вопрос как C++, я проголосовал за голосование - я обновлю вопрос –

ответ

2

Функция produceName будет объявить вернуть GattAttribute объект , но вы пытаетесь вернуть массив указателей на объекты GattAttribute. Вполне различие.

Но это не худшая часть вашего кода. Если вы исправите тип возвращаемого объявления, чтобы код сработал, у вас будет еще худшая проблема, которая приведет к неопределенным поведением: вы возвращаете указатели на локальные переменные. Как только функция вернется, эти локальные переменные перестанут существовать, и любой указатель на них не может быть использован.

+0

'nameDescr' является переменной? –

+0

Что вы предлагаете - это лучший подход? –

+0

@SouravGhosh 'nameDescr' действительно является объектом' GattAttribute' –

1

Прежде всего: обратите внимание, что массив pdescriptors в исходном коде только один элемент длинный. Таким образом, прямой указатель на объект будет работать просто отлично, или если бы процент заполнения не ожидал массив указателей. Мы можем имитировать это путем передачи указателя на указатель и размера 1. Учтите: вычисление sizeof(...)/sizeof(...) в исходном коде также предназначено для возврата 1, и это становится сложным, когда вы вводите границы функций (в частности, когда вы передаете массив как аргумент функции).

Кроме того, ваш вопрос несколько неясен: вы намерены использовать разные значения GattAttribute? Если нет, то вы, вероятно, могли бы сделать что-то вроде:

void updatePercentage(WhateverTypeValueBytesIs valueBytes) { 
    GattAttribute nameDescr(BLE_UUID_DESCRIPTOR_CHAR_USER_DESC, (uint8_t *)"Percentage", strlen("Percentage")); 
    GattAttribute * ptr = &nameDescr; // needed, because we want to pass pointer-to-pointer-to-nameDescr 
    PercentageFill(PercentageUUID, valueBytes.getPointer(), 
       valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 
       GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
       &ptr, 1), /* are we sure about trailing comma here? */ 
    // other relevant trailing code? 
} 

Судя по сообщению об ошибке о недосягаемом копирования конструктору Вы упоминали в комментариях, GattAttribute, вероятно, обычный конструктор, так что нет необходимости создавать дополнительные функции там.Если вы хотите превратить этот конкретный GattAttribute во что-то, что вы можете скрыть за функциональным интерфейсом и «искать» по желанию, тогда вы можете превратить его в одноэлементный подобный (например, другие способы достижения той же цели существуют):

GattAttribute * getNameDescriptor(void) { 
    static GattAttribute nameDescr(BLE_UUID_DESCRIPTOR_CHAR_USER_DESC, (uint8_t *)"Percentage", strlen("Percentage")); 
    return &nameDescr; 
} 

Затем вы можете использовать эту функцию, как это:

void updatePercentage(WhateverTypeValueBytesIs valueBytes) { 
    GattAttribute * ptr = getNameDescriptor(); // needed, because we want to pass pointer-to-pointer-to-nameDescr 
    PercentageFill(PercentageUUID, valueBytes.getPointer(), 
       valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 
       GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
       &ptr, 1), /* are we sure about trailing comma here? */ 
    // other relevant trailing code? 
} 

EDIT, чтобы добавить дополнительный вариант (ы) на основе комментариев:

void updatePercentage(WhateverTypeValueBytesIs valueBytes, const char* name) { 
    GattAttribute nameDescr(BLE_UUID_DESCRIPTOR_CHAR_USER_DESC, (const uint8_t *) name, strlen(name)); 
    GattAttribute * ptr = &nameDescr; // needed, because we want to pass pointer-to-pointer-to-nameDescr 
    PercentageFill(PercentageUUID, valueBytes.getPointer(), 
       valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 
       GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
       &ptr, 1), /* are we sure about trailing comma here? */ 
    // other relevant trailing code? 
} 

Или другой вариант: тривиальный, проходит в полностью инициализирован GattAttribute по ссылке:

void updatePercentage(WhateverTypeValueBytesIs valueBytes, GattAttribute & descr) { 
    GattAttribute * ptr = &descr; // needed, because we want to pass pointer-to-pointer-to-descr 
    PercentageFill(PercentageUUID, valueBytes.getPointer(), 
       valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES, 
       GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES, 
       &ptr, 1), /* are we sure about trailing comma here? */ 
    // other relevant trailing code? 
} 

Что вы называете, как это:

void foo(WhateverTypeValueBytesIs valueBytes) { 
    GattAttribute nameDescr(BLE_UUID_DESCRIPTOR_CHAR_USER_DESC, (uint8_t *)"Percentage", strlen("Percentage")); 
    updatePercentage(valueBytes, nameDescr); 
} 

Очевидно, что вместо использования ссылок вы можете также переделки функции, чтобы взять указатель к объекту GattAttribute (и используйте это вместо переменной ptr так же, как в примерах используется переменная ptr).

Дополнительное дополнение: обратите внимание, что вы, вероятно, захотите избежать копирования valueBytes, когда вы передадите его updatePercentage, и здесь вы, вероятно, захотите передать его по ссылке.

+0

Спасибо. Вы задали несколько вопросов: повторный код и т. Д. После заполнения процента, есть несколько других характеристик, которые нужно настроить, с разными именами, следовательно, конечная запятая и желание сделать этот код повторно используемым. Поэтому в идеале я хотел бы передать дескриптор строки в функцию и вернуть массив для этой строки, если это имеет смысл? –

+0

В любом случае я могу структурировать то, что вы положили, работать для разных разных имен? –

+0

@GeorgeEdwards, очевидно, вы можете взять первый вариант и изменить его, поэтому 'updatePercentage' принимает дополнительный аргумент' const char * name' и использует это вместо жестко закодированного значения '' Percentage'' ... – user268396