嗨,我试着用esp32做一个简单的测试。我从编译器那里得到了错误,这些错误不是针对我的.cpp和.hpp的,而是针对esp-国防军的,这是不应该发生的。我认为我的文件中存在一些东西,这是在误导编译器。
我使用esp-idf = v4.4,vscode espressif插件1.2
所以问题在BLE_UUID16_DECLARE上。
我现在的代码是:
#include <stdio.h>
#include "nvs_flash.h"
#include "esp_log.h"
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "host/ble_uuid.h"
#include "myBle.hpp"
#define DEVICE_NAME "My BLE Device"
#define DEV_INFO 0x180A
#define MANUFACTURER 0x2A29
uint8_t ble_address_type;
const ble_uuid_t* devInfoUuid= BLE_UUID16_DECLARE(DEV_INFO);
const ble_uuid_t* manufacturerUuid= BLE_UUID16_DECLARE(MANUFACTURER);
static int device_info(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg){
os_mbuf_append(ctxt->om,"Achieved",strlen("Achieved"));
return 0;
}
const struct ble_gatt_chr_def gatt_chrs[]={
{
.uuid = manufacturerUuid,
.access_cb = device_info,
.flags = BLE_GATT_CHR_F_READ
},
{
0
}
};
static const struct ble_gatt_svc_def gat_svcs[]= {
{
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = devInfoUuid,
.characteristics = gatt_chrs
},
{
0,
}
};最初我也在一次块中创建了这个结构,但是问题是一样的。代码是这样的:
#define DEV_INFO 0x180A
#define MANUFACTURER 0x2A29
static int device_info(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg){
os_mbuf_append(ctxt->om,"Achieved",strlen("Achieved"));
return 0;
}
static const struct ble_gatt_svc_def gat_svcs[] = {
{
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(DEV_INFO),
.characteristics = (struct ble_gatt_chr_def[])
{
{
.uuid = BLE_UUID16_DECLARE(MANUFACTURER),
.access_cb = device_info,
.flags = BLE_GATT_CHR_F_READ
},
{
0,
},
}
},
{
0,
},
};我还尝试将定义的十六进制立即放入函数中,但结果是相同的。
错误出现在BLE_UUID16_DECLARE的problems选项卡上:
{“资源”:"/Users/kyrpav/workspace/esp32/tutorials/LearnEsp32/main/Lesson12/myBle.cpp",“所有者”:"C/C++",“代码”:"18",“严重性”:8,“消息”:“预期a ')'",”源“:"C/C++","startLineNumber":29,"startColumn":17,"endLineNumber":29,"endColumn":35 }
同一部分的第二个错误是:
{“资源”:"/Users/kyrpav/workspace/esp32/tutorials/LearnEsp32/main/Lesson12/myBle.cpp",“所有者”:"cpp",“严重性”:8,“消息”:“在'}‘令牌之前的预期声明”,"startLineNumber":41,"startColumn":5,"endLineNumber":41,"endColumn":5}
如果你检查终端,你会看到:
/Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:102:36:错误:预期主-表达式在‘)令牌( ble_uuid_t ) (&(ble_uuid16_t) BLE_UUID16_INIT(Uuid16))^./main/Lesson12 12/myBle.cpp:19:32:注意:在宏'BLE_UUID16_DECLARE’const ble_uuid_t devInfoUuid= BLE_UUID16_DECLARE(DEV_INFO)的扩展中;^~ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:84:5:错误:预期‘’之前的'{‘令牌{\^ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:102:38:注:在展开宏'BLE_UUID16_INIT’((ble_uuid_t )(&)( ble_uuid16_t) BLE_UUID16_INIT(Uuid16))^~./main/Lesson12 12/myBle.cpp:19:32:注:在宏'BLE_UUID16_DECLARE‘const ble_uuid_t devInfoUuid= BLE_UUID16_DECLARE(DEV_INFO)的扩展中;^~ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:102:21:注:为了匹配这个'(‘( ble_uuid_t )(&ble_uuid16_t)BLE_UUID16_INIT(Uuid16)^../main/Lesson12 12/myBle.cpp:19:32:注:注意:在宏'BLE_UUID16_DECLARE’const ble_uuid_t devInfoUuid= BLE_UUID16_DECLARE(DEV_INFO)的扩展中;^~ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:102:36:错误:预期主-表达式前‘’令牌((ble_uuid_t ) (&(ble_uuid16_t) BLE_UUID16_INIT(Uuid16)^./main/Lesson12 12/myBle.cpp:20:37:注意:在扩展宏'BLE_UUID16_DECLARE‘const ble_uuid_t manufacturerUuid= BLE_UUID16_DECLARE(制造商);^~ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:84:5:错误:预期‘’之前的'{‘令牌{\^ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:102:38:注:在展开宏'BLE_UUID16_INIT’((ble_uuid_t )(&)( ble_uuid16_t) BLE_UUID16_INIT(Uuid16))^~./main/Lesson12 12/myBle.cpp:20:37:注:在宏'BLE_UUID16_DECLARE‘const ble_uuid_t manufacturerUuid= BLE_UUID16_DECLARE(制造商)的扩展中;^~ /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:102:21:注:为了匹配这个‘( ble_uuid_t )(&ble_uuid16_t)BLE_UUID16_INIT(Uuid16)^../main/Lesson12 12/myBle.cpp:20:37:注意:注意:在宏'BLE_UUID16_DECLARE’const ble_uuid_t manufacturerUuid= BLE_UUID16_DECLARE(制造商)的扩展中;
看来我找到了问题的真正原因。
原因是
extern "C"
{
void app_main();
}我所拥有的项目是在cpp中,我正在以正常的方式使用extern功能。
我在.c中创建了一个新项目,一切顺利。作为第二步,我甚至将ble代码放置在不同的.c和.h文件中,它工作得很好。
然后,我将文件重命名为cpp和hpp,修复Makefile,在构建时得到相同的错误:
../main/myBle.cpp:34: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/myBle.cpp:34: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:103:21:
note: to match this '('
((ble_uuid_t *) (&(ble_uuid16_t) BLE_UUID16_INIT(uuid16)))
^ ../main/myBle.cpp:34: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:103:62:
error: expected '}' before ')' token
((ble_uuid_t *) (&(ble_uuid16_t) BLE_UUID16_INIT(uuid16)))
^ ../main/myBle.cpp:34:17: note: in expansion of macro
'BLE_UUID16_DECLARE'
.uuid = BLE_UUID16_DECLARE(DEVICE_INFO_SERVICE),
^~~~~~~~~~~~~~~~~~ ../main/myBle.cpp:32:5: note: to match this '{'
{
^ In file included from /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_adv.h:24,
from /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_gap.h:32,
from /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_hs.h:33,
from ../main/myBle.cpp:7: /Users/kyrpav/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_uuid.h:103:62:
error: expected '}' before ')' token
((ble_uuid_t *) (&(ble_uuid16_t) BLE_UUID16_INIT(uuid16)))
^ ../main/myBle.cpp:34:17: note: in expansion of macro
'BLE_UUID16_DECLARE'
.uuid = BLE_UUID16_DECLARE(DEVICE_INFO_SERVICE),
^~~~~~~~~~~~~~~~~~ ../main/myBle.cpp:31:51: note: to match this '{' static const struct ble_gatt_svc_def gat_svcs[] = {
^ ../main/myBle.cpp:47:5: error: expected declaration before '}' token
},
^ ../main/myBle.cpp:24:12: warning: 'int device_info(uint16_t, uint16_t, ble_gatt_access_ctxt*, void*)' defined but not used
[-Wunused-function] static int device_info(uint16_t conn_handle,
uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
^~~~~~~~~~~发布于 2022-10-29 12:35:45
可悲的是,灵活的代码无法用C++立即编译。它大量使用指定的初始值和复合字面值,这两个特性在C和C++之间有细微的区别。
特别是后者是一个真正的痛苦,需要一些样板代码来解决。原因可以在gcc的复合文字文档中找到。
在C中,复合文字指定具有静态或自动存储持续时间的未命名对象。在C++中,复合文字指定一个临时对象,该对象只存在到其完整表达式的末尾。因此,使用复合文字的子对象地址的定义良好的C代码可以在C++中未定义,因此G++拒绝将临时数组转换为指针。例如,如果上面的数组复合文字示例出现在函数中,那么在C++中任何后续使用foo都会有未定义的行为,因为数组的生存期在foo声明之后结束。
但是,将BLE服务特性从服务结构中提取出来,就像您在第一个示例中所做的那样,应该足以解决这个问题。
对于UUID宏,您可以用一些符合C++的宏替换来自nimble的宏。例如,用于UUID16的宏可以类似于
#define UUID16(uuid16) \
std::invoke([] { \
static constexpr ble_uuid16_t uuid{.u = BLE_UUID_TYPE_16, \
.value = uuid16}; \
return std::bit_cast<ble_uuid_t*>(&uuid); \
})https://stackoverflow.com/questions/69939061
复制相似问题