Unavailable: function like macros not supported

First of all I want to apologize if this is the wrong place to post this.

I have been messing around with Swift Embedded now for a little bit and I'm trying to set up a BLE Gatt server on a ESP32. Im trying to follow this walkthrough but writing in Swift ofc.

Im trying to call BT_CONTROLLER_INIT_CONFIG_DEFAULT() which is a function style macro but I get the following error when compiling:

/Users/naknut/Developer/esp32-ble-swift/main/BLE.swift:6:31: error: cannot find 'BT_CONTROLLER_INIT_CONFIG_DEFAULT' in scope
 4 | 
 5 |     init() {
 6 |         let bluetoothConfig = BT_CONTROLLER_INIT_CONFIG_DEFAULT()
   |                               `- error: cannot find 'BT_CONTROLLER_INIT_CONFIG_DEFAULT' in scope
 7 |         guard esp_bt_controller_init(bluetoothConfig) == ESP_OK else {
 8 |             fatalError("initialize controller failed")

/Users/naknut/esp/esp-idf/components/bt/include/esp32c6/include/esp_bt.h:223:9: note: macro 'BT_CONTROLLER_INIT_CONFIG_DEFAULT' unavailable: function like macros not supported
221 | } esp_bt_controller_config_t;
222 | 
223 | #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {                                           \
    |         `- note: macro 'BT_CONTROLLER_INIT_CONFIG_DEFAULT' unavailable: function like macros not supported
224 |     .config_version = CONFIG_VERSION,                                                   \
225 |     .ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE,                        \

Is there any way to get around this?

Swift's C interop can't directly interact with preprocessor macros except in a few limited situations like literal values. You might be able to wrap the macro invocation in a static inline function from a C header file and import that instead, like:

static inline bt_controller bt_controller_init_config_default(void) {
  return BT_CONTROLLER_INIT_CONFIG_DEFAULT();
}
4 Likes

Thanks for your help @Joe_Groff !

I tried defining the function like this in the BridgingHeader.h-file

static inline esp_bt_controller_config_t bt_controller_init_config_default(void)
{
    return BT_CONTROLLER_INIT_CONFIG_DEFAULT();
}

and now I get a new error:

<unknown>:0: error: failed to emit precompiled header '/var/folders/ls/h7hs2hk92g7_qynprm35gyqw0000gn/T/TemporaryDirectory.ZpmBXc/BridgingHeader.pch' for bridging header '/Users/naknut/Developer/esp32-ble-swift/main/BridgingHeader.h'
/Users/naknut/Developer/esp32-ble-swift/main/BridgingHeader.h:21:12: error: expected expression
19 | static inline esp_bt_controller_config_t bt_controller_init_config_default(void)
20 | {
21 |     return BT_CONTROLLER_INIT_CONFIG_DEFAULT();
   |            `- error: expected expression
22 | }

/Users/naknut/esp/esp-idf/components/bt/include/esp32c6/include/esp_bt.h:223:45: note: expanded from macro 'BT_CONTROLLER_INIT_CONFIG_DEFAULT'
221 | } esp_bt_controller_config_t;
222 | 
223 | #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {                                           \
    |                                             `- note: expanded from macro 'BT_CONTROLLER_INIT_CONFIG_DEFAULT'
224 |     .config_version = CONFIG_VERSION,                                                   \
225 |     .ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE,                        \

I changed the function to this:

static inline esp_bt_controller_config_t bt_controller_init_config_default(void)
{
    esp_bt_controller_config_t config = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    return config;
}

and now it compiles!

I apologise if these questions are a little dumb, its been ages since I coded in C😅

I also want to implement BLE with Swift but did not yet had the time to start working on it. If you share your repo we maybe can join forces.

Absolutely! I don’t really have anything working yet. Just trying to figure out how to get started. But as soon as I have something working I’ll put up a repo and let you know.

1 Like