我正在尝试使用 Windows 的蓝牙 API 从心率监测器获取心率,但我遇到了蓝牙 GATTRegisterEvent 函数的问题,即第四个参数,它需要PFNBLUETOOTH_GATT_EVENT_CALLBACK回调函数作为参数。执行以下代码可以正常工作:
// Function definition
void SomeEvent(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
{ /* Function code */}
// Calling BluetoothGATTRegisterEvent
hr = BluetoothGATTRegisterEvent(
hLEDevice,
EventType,
&EventParameterIn,
SomeEvent,
NULL,
&EventHandle,
BLUETOOTH_GATT_FLAG_NONE);
但是,如果我尝试传递成员函数(例如HeartRateMonitor::SomeEvent而不仅仅是SomeEvent(,则会出现以下错误:
argument of type "void (HeartRateMonitor::*)(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)" is incompatible with parameter of type "PFNBLUETOOTH_GATT_EVENT_CALLBACK"
我的第一直觉是尝试使用函数指针或 std::bind 对象,但两者都不起作用。将回调函数作为此参数传递时是否需要进行一些特殊考虑,或者我是否缺少有关成员函数的明显内容?
BluetoothGATTRegisterEvent
的CallbackContext
参数的用途。
必须传递static
成员函数作为回调,this
作为CallbackContext
传递。非静态成员函数有一个隐式this
作为第一个参数(__thiscall
(,不能用作回调。
在回调中,您可以将Context
强制转换为this
并访问类的其他成员。
例:
class HeartRateMonitor {
public:
//...
void MemberFun(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
{}
static void StaticMemberFun(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
{
HeartRateMonitor* pThis = static_cast<HeartRateMonitor*>(Context);
/* Function code */
// and here you could access your class non-static data by pThis->...
// or call a non-static method, so you don't need to always writhe `pThis`
}
HeartRateMonitor()
{
HANDLE hLEDevice = 0;
BTH_LE_GATT_EVENT_TYPE EventType = CharacteristicValueChangedEvent;
PVOID EventParameterIn = 0;
BLUETOOTH_GATT_EVENT_HANDLE EventHandle = 0;
HRESULT hr = 0;
hr = ::BluetoothGATTRegisterEvent( // ok
hLEDevice,
EventType,
&EventParameterIn,
&HeartRateMonitor::StaticMemberFun,
this,
&EventHandle,
BLUETOOTH_GATT_FLAG_NONE);
hr = ::BluetoothGATTRegisterEvent( // error C2664: 'unsigned long BluetoothGATTRegisterEvent(HANDLE,BTH_LE_GATT_EVENT_TYPE,void *,PFNBLUETOOTH_GATT_EVENT_CALLBACK,void *,BLUETOOTH_GATT_EVENT_HANDLE *,unsigned long)': cannot convert argument 4 from 'void (__cdecl HeartRateMonitor::* )(BTH_LE_GATT_EVENT_TYPE,void *,void *)' to 'PFNBLUETOOTH_GATT_EVENT_CALLBACK'
hLEDevice,
EventType,
&EventParameterIn,
&HeartRateMonitor::MemberFun,
this,
&EventHandle,
BLUETOOTH_GATT_FLAG_NONE);
}
};
例
在函数名称前加上"CALLBACK":
// Function definition
void CALLBACK SomeEvent(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
{ /* Function code */}
它对我有用(VC 2019 和 mingw(。