这是我对 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)))
根据需要调整返回类型。再次,与其他解决方案相比,它被认为是次优解决方案。