You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用Win32 API注册GATT特征值变更通知遇0x57错误求助

排查C#调用BluetoothGATTRegisterEvent返回0x57(E_INVALIDARG)错误的建议

我正尝试通过C#调用Win32 API注册GATT特征值变更通知,已成功获取设备句柄、相关GATT服务及特征。但调用BluetoothGATTRegisterEvent时始终返回0x57(E_INVALIDARG)错误,且无明确无效参数提示。尝试过更换第一个参数为设备句柄或特征的ServiceHandle等多种参数组合,均无效。以下是调用该API所用的结构体定义及代码(服务与特征发现部分功能正常,已省略):

public enum BTH_LE_GATT_EVENT_TYPE
{
    CharacteristicValueChangedEvent = 0
}

[StructLayout(LayoutKind.Sequential)]
public struct BLUETOOTH_GATT_NOTIFICATION_REGISTRATION
{
    public ushort NumCharacteristics;
    public BTH_LE_GATT_CHARACTERISTIC[] Characteristics;
}

[StructLayout(LayoutKind.Sequential)]
public struct BLUETOOTH_GATT_EVENT_HANDLE
{
    public IntPtr handle;
}

// Define the callback delegate
internal delegate void PFNBLUETOOTH_GATT_EVENT_CALLBACK(
    BTH_LE_GATT_EVENT_TYPE EventType,
    IntPtr EventOutParameter,
    IntPtr Context
);

[DllImport("BluetoothApis.dll", SetLastError = true)]
public static extern uint BluetoothGATTRegisterEvent(
    ushort Service,
    BTH_LE_GATT_EVENT_TYPE eventType,
    ref BLUETOOTH_GATT_NOTIFICATION_REGISTRATION eventParameterIn,
    PFNBLUETOOTH_GATT_EVENT_CALLBACK callback,
    IntPtr context,
    ref BLUETOOTH_GATT_EVENT_HANDLE eventHandle,
    uint Flags
);

public void RegisterEvents(
    SafeFileHandle deviceHandle,
    BTH_LE_GATT_SERVICE service,
    BTH_LE_GATT_CHARACTERISTIC characteristic,
    PFNBLUETOOTH_GATT_EVENT_CALLBACK eventHandler
)
{
    var eventHandle = new BLUETOOTH_GATT_EVENT_HANDLE();
    var eventParameters = new BLUETOOTH_GATT_NOTIFICATION_REGISTRATION
    {
        NumCharacteristics = 1,
        Characteristics = new[] { characteristic }
    };

    BluetoothGATTRegisterEvent(
        characteristic.ServiceHandle,
        BTH_LE_GATT_EVENT_TYPE.CharacteristicValueChangedEvent,
        ref eventParameters,
        eventHandler,
        IntPtr.Zero,
        ref eventHandle,
        BLUETOOTH_GATT_FLAG_NONE
    );
}

问题排查建议

  • 修正参数类型:BluetoothGATTRegisterEvent的第一个参数Service应为IntPtr(对应Win32的HANDLE类型),当前定义为ushort会导致参数长度不匹配,这是触发E_INVALIDARG的高概率原因。
  • 调整结构体数组的封送方式:BLUETOOTH_GATT_NOTIFICATION_REGISTRATION中的Characteristics数组需要添加[MarshalAs(UnmanagedType.LPArray)]特性,否则非托管代码无法正确识别数组指针,修改后的结构体定义如下:
    [StructLayout(LayoutKind.Sequential)]
    public struct BLUETOOTH_GATT_NOTIFICATION_REGISTRATION
    {
        public ushort NumCharacteristics;
        [MarshalAs(UnmanagedType.LPArray)]
        public BTH_LE_GATT_CHARACTERISTIC[] Characteristics;
    }
    
  • 指定回调委托的调用约定:在PFNBLUETOOTH_GATT_EVENT_CALLBACK委托上添加[UnmanagedFunctionPointer(CallingConvention.StdCall)]特性,确保与Win32 API的调用约定一致:
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    internal delegate void PFNBLUETOOTH_GATT_EVENT_CALLBACK(
        BTH_LE_GATT_EVENT_TYPE EventType,
        IntPtr EventOutParameter,
        IntPtr Context
    );
    
  • 校验特征属性:确认目标特征的CharacteristicProperties包含CharacteristicNotify或CharacteristicIndicate标志,API不允许为不支持通知/指示的特征注册事件。
  • 检查句柄有效性:再次确认characteristic.ServiceHandle是有效的GATT服务句柄,避免因类型转换导致句柄值被截断或篡改。
  • 验证Flags参数:确保BLUETOOTH_GATT_FLAG_NONE的常量值为0,与Win32定义一致。

内容的提问来源于stack exchange,提问作者Morten Lemvigh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:34:56