I have hit a wall recently. The summary would be the following: I would like to wrap a pub extern "C" fn on_sync() { ... } such that when it is called I can also call a method named pub fn on_sync(&self) { ... } defined in an impl of a struct BluetoothDevice.
The struct BluetoothDevice and its impl can be found below:
use super::helpers;
use crate::lib::log::log::Logger;
use esp_idf_sys;
extern crate alloc;
pub struct BluetoothDevice<'a> {
    logger: &'a Logger,
}
impl<'a> BluetoothDevice<'a> {
    pub fn new(logger: &'a Logger) -> Self {
        BluetoothDevice { logger }
    }
    pub fn init(&self) {
        unsafe {
            // ...
            esp_idf_sys::ble_hs_cfg.sync_cb = Some(helpers::on_sync);
            esp_idf_sys::ble_hs_cfg.reset_cb = Some(helpers::on_reset);
            // ...
        }
    }
    pub fn on_sync(&self) {}
    pub fn on_reset(&self) {}
}
And the helpers module can be found below:
use super::device;
struct BluetoothGAPWorkaround<'a> {
    instance: Option<&'a device::BluetoothDevice<'a>>,
}
static mut BLUETOOTH_GAP_WORKAROUND: BluetoothGAPWorkaround =
    BluetoothGAPWorkaround { instance: None };
pub extern "C" fn on_sync() {
    unsafe {
        match BLUETOOTH_GAP_WORKAROUND.instance {
            Some(device) => device.on_sync(),
            None => return,
        }
    }
}
pub extern "C" fn on_reset() {
    unsafe {
        match BLUETOOTH_GAP_WORKAROUND.instance {
            Some(device) => device.on_reset(),
            None => return,
        }
    }
}
pub fn set_device<'a>(bluetoothDevice: &'a device::BluetoothDevice<'a>) {
    unsafe {
        if let None = BLUETOOTH_GAP_WORKAROUND.instance {
            BLUETOOTH_GAP_WORKAROUND.instance = Some(bluetoothDevice);
        };
    }
}
The problem with the Rust helpers module is the fact that I keep hitting a wall in the pub fn set_device<'a>(...) { ... } function due to the following error: lifetime may not live long enough assignment requires that "'a" must outlive "'static".
Would there be any solution of wrapping pub extern "C" on_sync() { ... } such that I can call device.on_sync(), preferrably without having to set the device as a static variable?
Previously I hit this issue in C++ too and I fixed it with the following and would like to perform the same thing in Rust:
#include "bluetoothGAPWorkarounds.h"
#include <host/ble_hs.h>
struct BluetoothGAPWorkaround
{
    boundOnSyncCallback *onSyncCallback;
    boundOnResetCallback *onResetCallback;
    void *onSyncCallbackArg;
    void *onResetCallbackArg;
} workaround;
static void unboundOnSyncCallback(void)
{
    if (!workaround.onSyncCallback)
    {
        return;
    }
    workaround.onSyncCallback(&workaround.onSyncCallbackArg);
}
static void unboundOnResetCallback(int reason)
{
    if (!workaround.onResetCallback)
    {
        return;
    }
    workaround.onResetCallback(reason, &workaround.onResetCallbackArg);
}
void setOnSyncCallback(boundOnSyncCallback callback, void *arg)
{
    workaround.onSyncCallback = callback;
    workaround.onSyncCallbackArg = arg;
    ble_hs_cfg.sync_cb = unboundOnSyncCallback;
}
void setOnResetCallback(boundOnResetCallback callback, void *arg)
{
    workaround.onResetCallback = callback;
    workaround.onResetCallbackArg = arg;
    ble_hs_cfg.reset_cb = unboundOnResetCallback;
}
I needed I can use the code above in a thin C++ wrapper that I can access from the Rust code, but that would not be ideal.