如何从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
相关产品推荐
相关产品推荐

