无论如何,在初始化列表之前调用CoInitialize()

Anyway to call CoInitialize() before an initialization list?

本文关键字:调用 CoInitialize 初始化 列表 无论如何      更新时间:2023-10-16

这是我对 ThorDetectorSwitch 构造函数.cpp文件的C++代码:

ThorDetectorSwitch::ThorDetectorSwitch() : _mcSwitch(__uuidof(MCLControlClass))
{
    _A  = WstringToBSTR(L"A"); 
    _B  = WstringToBSTR(L"B");
    _C  = WstringToBSTR(L"C");
    _D  = WstringToBSTR(L"D");
    _deviceDetected = FALSE;
}

如您所见,初始化列表 _mcSwitch(__uuidof(MCLControlClass)) 用于初始化 COM 对象(MCLControlClass,从 COM dll 注册(。

我想知道是否可以在此初始化列表之前调用CoInitialize((?因为我收到"CoInitialize((尚未调用"的异常。或者任何其他方法可以避免此异常?

多谢。

首先,我建议您使用 CoInitializeEx 而不是 CoInitialize 。甚至 MSDN 文档也建议这样做。其次,我建议您在main()中以及在需要使用 COM 对象的每个附加线程的开头调用 CoInitializeEx。这是有充分理由的。例如,在线程结束之前,对CoInitializeEx的每个调用都应该有一个相应的CoUninitialize调用。这可确保正确终止 COM 库。如果从构造函数调用它,则还必须管理 COM 库的初始化次数,以便对CoUninitialize进行正确次数的调用。另一个问题是,当后续调用使用不同公寓型号CoInitializeEx时,它将失败。如果发生这种情况,并且您的构造函数正在检查错误,例如实例化期间最终会出现失败条件。如何处理构造函数中的此类错误条件?通过抛出一个例外 - 这不是一件非常愉快的事情。

我的最后一个建议是阅读文档并以正确的方式做事,否则您最终会像过去几天一样挠头。

我同意那些建议将此类 init 留给 main(( 或 InitInstance 以及其他改进的人,但让我展示原始问题的一种解决方案。

由于调用函数会产生责任,因此从 RAII 包装器开始,如下所示:

class ComIniter
{
public:
    ComIniter() { CoInitialize(); } // or use ex, add params, etc
    ~ComIniter() { CoUnInitialize(); } // adjust to match
private:
    ComIniter(const ComIniter&);  // =delete with C++11
    ComIniter& opeartor=(const ComIniter&); // =delete with C++11
};

可以在 main((、线程函数的开头和/或命名空间范围将实例放在需要 COM 的其他静态对象之前。

如果你决定反对这些并想要最初的想法,在ThorDetectorSwitch中添加:

private: static const char* ComHelper(const char* arg) { static ComIniter c; return arg; }

然后将其与初始化列表一起使用:

ThorDetectorSwitch::ThorDetectorSwitch() : _mcSwitch(ComHelper(__uuidof(MCLControlClass)))

根据需要调整返回类型。再次,与其他解决方案相比,它被认为是次优解决方案。