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

如何从IntPtr获取IChannelControl实例名称及判断其类型?

问题:FMOD错误回调中区分ChannelControl实例类型并获取名称

我在FMOD中注册了错误回调函数,尝试通过callbackInfo.instance获取实例名称用于调试,但callbackInfo.instancetype返回ERRORCALLBACK_INSTANCETYPE.CHANNELCONTROL,这个类型对应IChannelControl接口,它既可以代表Channel也可以代表ChannelGroup实例,无法直接判断具体类型,类型选错的话会拿到无效数据。

我的回调代码如下:

var errorCallback = new FMOD.SYSTEM_CALLBACK(ERROR_CALLBACK);
system.setCallback(errorCallback, FMOD.SYSTEM_CALLBACK_TYPE.ERROR);

private static FMOD.RESULT ERROR_CALLBACK(IntPtr system, FMOD.SYSTEM_CALLBACK_TYPE type, IntPtr commanddata1, IntPtr commanddata2, IntPtr userdata)
{
    FMOD.ERRORCALLBACK_INFO callbackInfo = Marshal.PtrToStructure<FMOD.ERRORCALLBACK_INFO>(commanddata1);

    if(callbackInfo.instancetype == ERRORCALLBACK_INSTANCETYPE.CHANNELGROUP)
    {
        // 获取callbackInfo.instance的名称或其他标识符
    }
}

我需要一种方法来判断这个实例到底是Channel还是ChannelGroup,或者不用判断类型就能直接获取名称。

补充说明:Channel和ChannelGroup都有接收IntPtr的构造函数,这是我找到的唯一创建对象的方式;像处理ERRORCALLBACK_INFO那样做封送处理无效,因为这些结构体只是C++对象的包装,没有实际数据。


解决方案

方法1:通过FMOD原生接口判断类型(推荐)

FMOD的ChannelControl基类提供了getType方法,可以直接返回实例的具体类型,这是最可靠的判断方式。拿到类型后再转换成对应实例获取名称:

private static FMOD.RESULT ERROR_CALLBACK(IntPtr system, FMOD.SYSTEM_CALLBACK_TYPE type, IntPtr commanddata1, IntPtr commanddata2, IntPtr userdata)
{
    FMOD.ERRORCALLBACK_INFO callbackInfo = Marshal.PtrToStructure<FMOD.ERRORCALLBACK_INFO>(commanddata1);

    if (callbackInfo.instancetype == FMOD.ERRORCALLBACK_INSTANCETYPE.CHANNELCONTROL)
    {
        // 先包装为ChannelControl基类对象
        var channelControl = new FMOD.ChannelControl(callbackInfo.instance);
        FMOD.CHANNELCONTROL_TYPE controlType;
        var result = channelControl.getType(out controlType);
        
        if (result == FMOD.RESULT.OK)
        {
            string name = string.Empty;
            const int bufferSize = 256; // 定义足够大的缓冲区避免名称截断
            switch (controlType)
            {
                case FMOD.CHANNELCONTROL_TYPE.CHANNEL:
                    var channel = new FMOD.Channel(callbackInfo.instance);
                    channel.getName(out name, bufferSize);
                    break;
                case FMOD.CHANNELCONTROL_TYPE.CHANNELGROUP:
                    var group = new FMOD.ChannelGroup(callbackInfo.instance);
                    group.getName(out name, bufferSize);
                    break;
            }
            // 输出调试信息
            Console.WriteLine($"出错实例名称:{name}");
        }
    }
    return FMOD.RESULT.OK;
}

方法2:尝试转换并校验结果(应急方案)

如果不想调用getType,可以先尝试将实例转为Channel,通过返回码判断是否成功;失败则再尝试转为ChannelGroup:

private static FMOD.RESULT ERROR_CALLBACK(IntPtr system, FMOD.SYSTEM_CALLBACK_TYPE type, IntPtr commanddata1, IntPtr commanddata2, IntPtr userdata)
{
    FMOD.ERRORCALLBACK_INFO callbackInfo = Marshal.PtrToStructure<FMOD.ERRORCALLBACK_INFO>(commanddata1);

    if (callbackInfo.instancetype == FMOD.ERRORCALLBACK_INSTANCETYPE.CHANNELCONTROL)
    {
        string name = string.Empty;
        const int bufferSize = 256;
        // 先尝试作为Channel处理
        var channel = new FMOD.Channel(callbackInfo.instance);
        var result = channel.getName(out name, bufferSize);
        
        if (result != FMOD.RESULT.OK)
        {
            // 转换失败则尝试作为ChannelGroup处理
            var group = new FMOD.ChannelGroup(callbackInfo.instance);
            group.getName(out name, bufferSize);
        }
        Console.WriteLine($"出错实例名称:{name}");
    }
    return FMOD.RESULT.OK;
}

关键注意事项

  • 所有FMOD API调用都要检查返回的FMOD.RESULT,确保操作成功后再使用数据。
  • getName方法需要传入足够大的缓冲区,避免名称被截断。
  • 优先使用getType方法判断类型,这是FMOD官方提供的类型区分方式,稳定性最高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:10:06