DirectSound初始化报错800401F0:未调用CoInitialize问题咨询
错误到底是什么?
你碰到的800401F0错误其实已经说得很直白了:当前线程还没调用CoInitialize,没法使用COM对象。
为什么会触发这个错误?
DirectSound是基于Windows COM(组件对象模型)实现的组件,所有DirectSound的核心对象都是COM对象。而COM的规则很明确:任何线程在创建或使用COM对象之前,必须先初始化该线程的COM运行环境——也就是调用CoInitialize或者CoInitializeEx。
你的代码直接加载了dsound.dll就去调用DirectSoundCreate,完全跳过了COM初始化这一步。而DirectSoundCreate内部会尝试创建DirectSound的COM实例,这时候系统发现当前线程没有COM上下文,就直接抛出了这个错误。
能不能绕过COM操作?
别想啦,完全不可能。DirectSound的整个架构都依赖COM,不管你是用静态链接dsound.lib的方式,还是像现在这样动态加载dsound.dll,只要你要使用DirectSound的任何功能,都必须先完成COM初始化。
怎么解决?
很简单,在调用DirectSoundCreate之前,加上COM初始化的代码就行。给你调整后的代码示例:
// 头文件中的代码... #define DIRECT_SOUND_CREATE(name) HRESULT WINAPI name(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter) typedef DIRECT_SOUND_CREATE(direct_sound_create); // 初始化代码... HMODULE DSoundLib = LoadLibraryA("dsound.dll"); if(DSoundLib) { // 先初始化COM环境 HRESULT comInit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // 允许重复初始化(S_FALSE表示当前线程已经初始化过COM) if (SUCCEEDED(comInit) || comInit == S_FALSE) { direct_sound_create *DirectSoundCreate = (direct_sound_create*) GetProcAddress(DSoundLib, "DirectSoundCreate"); LPDIRECTSOUND DirectSound; if(DirectSoundCreate && SUCCEEDED(DirectSoundCreate(0, &DirectSound,0))) { // 后续代码... } // 用完COM后记得清理 CoUninitialize(); } }
这里用CoInitializeEx而不是CoInitialize是因为它更灵活,COINIT_APARTMENTTHREADED是最常用的单线程公寓模型,适合大多数单线程音频场景。如果你的程序是多线程架构,可以根据需求换成COINIT_MULTITHREADED。
另外看你的链接器选项,已经包含了winmm.lib,这完全没问题;因为你是动态加载dsound.dll,所以不需要额外链接dsound.lib,如果后续要静态链接的话加上就行,但不管哪种方式,COM初始化都是必不可少的步骤。
内容的提问来源于stack exchange,提问作者MattMatt2000

