espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.89k stars 7.33k forks source link

BLE Nimble not working on cpp project (IDFGH-6222) #7895

Closed kyrpav closed 2 years ago

kyrpav commented 3 years ago

I have created a cpp project. I am using esp-idf v4.4 and vscode espressif plugin v1.2

in the main.cpp file i am using

extern "C" { void app_main(); }

normally and all cpp and hpp files in the project are working properly. I tried to make a simple ble project. And i get an error on ble_uuid16.h

/Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:103:36: error: expected primary-expression before ')' token ((ble_uuid_t *) (&(ble_uuid16_t) BLE_UUID16_INIT(uuid16))) ^ ../main/Lesson12/myBle.cpp:31:17: note: in expansion of macro 'BLE_UUID16_DECLARE' .uuid = BLE_UUID16_DECLARE(DEVICE_INFO_SERVICE), ^~~~~~ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:84:5: error: expected ')' before '{' token

/Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:103:38: note: in expansion of macro 'BLE_UUID16_INIT' ((ble_uuid_t *) (&(ble_uuid16_t) BLE_UUID16_INIT(uuid16)))

../main/Lesson12/myBle.cpp:28:51: note: to match this '{' static const struct ble_gatt_svc_def gat_svcs[] = { ^ ../main/Lesson12/myBle.cpp:44:5: error: expected declaration before '}' token },

And the problem starts from the gat_svcs[] definition. But the same code is working if you create a c project. If i try to explin it in order:

  1. I have create a c project and the code was working. All code in main.c file
  2. I have split the main.c and placed al ble code in different ble.c and ble.h and it was still working
  3. I have renamed .c to .cpp and .h and .hpp , updated the Makelist file to get the cpp files and also placed the extern "C" block and then the problem started.

`#define DEVICE_INFO_SERVICE 0x180A

define MANUFACTURER_NAME 0x2A29

static int device_info(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt ctxt, void arg) { const char * message = "Achieved Dreams"; os_mbuf_append(ctxt->om,"message",strlen("message")); return 0; }

static const struct ble_gatt_svc_def gat_svcs[] = { { .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = BLE_UUID16_DECLARE(DEVICE_INFO_SERVICE), .characteristics = (struct ble_gatt_chr_def[]){ { .uuid = BLE_UUID16_DECLARE(MANUFACTURER_NAME),

            .access_cb = device_info,

            .flags = BLE_GATT_CHR_F_READ,
        },
        {
            0,
        },
    } 
},
{
    0,
},

};`

negativekelvin commented 3 years ago

There are different rules for struct initialization between c and c++

kyrpav commented 3 years ago

Can you point to me the difference and how it should have been? For the ref https://en.cppreference.com/w/c/language/struct_initialization i do not see anything. Also over lets say 12 different training programs where i am doing the same type of initialisation i did not have any issue at all. So what do i miss.

negativekelvin commented 3 years ago

https://en.cppreference.com/w/cpp/language/aggregate_initialization

kyrpav commented 3 years ago

can you refactor it cause i tried to change to c++20 and do the

T object = { .designator = arg1 , .designator { arg2 } ... }; | (3) | (since C++20)   T object { .designator = arg1 , .designator { arg2 } ... }; | (4) | (since C++20)

but still it does not work. Also if you wanted to do .designator (cast to something) { arg2 }
is this going to work. I tried with casting and without and none compiled either o got more errors in any case.

kyrpav commented 3 years ago

From what i see in ble_uuid.h there is

#define BLE_UUID16_INIT(uuid16)         \
    {                                   \
        .u.type = BLE_UUID_TYPE_16,     \
        .value = (uuid16)               \
    }        

and u.type is not ok for cpp if i understand well from the reference you send. But this is in the esp-idf not in my code

0xjakob commented 3 years ago

@kyrpav Currently, a lot of the initializer macros in C work like this and will are incompatible with C++. So it's a problem we are aware of but which won't go away quickly. Is it a big problem re-writing the initialization in your code so that it is compatible with C++?

Like e.g.

#include <stdio.h>
struct Test {
    int a;
    float b;
};
extern "C" void app_main() {
    const Test t = {47, 0.47};
    printf("a: %d\n", t.a);
}
kyrpav commented 3 years ago

so you are asking to pick the initialisations from ble_uuid.h and re define them in my code so it works in cpp?

It is not big problem but i would like to avoid cause i do not know how deep in it goes. i hope this is only two macros for the declare and the init.

rahult-github commented 2 years ago

Closing ticket on esp-idf. Please feel free to reopen , if issue still seen.

freitasartur commented 2 years ago

so you are asking to pick the initialisations from ble_uuid.h and re define them in my code so it works in cpp?

It is not big problem but i would like to avoid cause i do not know how deep in it goes. i hope this is only two macros for the declare and the init.

Were you able to fix this? If so, what is the proper to do that?

Thanks in advance