2013-06-14 2 views
0

Вот мой C++ код в конструкторе ThorDetectorSwitch.cpp файла:В любом случае, чтобы вызвать CoInitialize() перед списком инициализации?

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() не назывался». Или любой другой способ избежать этого исключения?

Большое спасибо.

+0

Не используйте его класс 'CoInitialize' перед его построением. Вместо этого вызовите 'CoInitialize' перед созданием этого класса. –

+0

Вам лучше сосредоточиться на том, почему этот конструктор работает слишком рано. Порядок инициализации - нерешенная проблема в C++. –

ответ

2

Сначала я рекомендую использовать CoInitializeEx вместо CoInitialize. Это рекомендует даже документация MSDN. Во-вторых, я рекомендую вам позвонить CoInitializeEx в main() и в начале каждого дополнительного потока, который требует использования COM-объектов. Для этого есть веские причины. Например, каждый вызов CoInitializeEx должен иметь соответствующий вызов CoUninitialize до окончания потока. Это гарантирует, что библиотека COM будет правильно завершена. Если вы вызываете его из конструктора, вы также должны управлять количеством раз, когда библиотека COM инициализируется, поэтому производится правильное количество вызовов до CoUninitialize. Еще одна проблема заключается в том, что при последующих звонках в CoInitializeEx с другой квартирной моделью это не удастся. Если это произойдет, и ваш конструктор проверяет наличие ошибок, таких как должно быть, вы получите условие отказа во время создания экземпляра. Как вы обрабатываете условие ошибки, подобное этому в конструкторе? Бросив исключение - не очень приятная вещь.

Моя последняя рекомендация прочитайте документацию и сделайте все правильно, иначе вы в конечном итоге почесываете голову так, как будто это было за последние несколько дней.

+0

@Captian Спасибо очень mich за ваше объяснение. Я поместил CoInitialize (NULL) в DllMain(), который находится в другом файле C++ из моего ThorDetectorSwitch.cpp, так или иначе он тоже не работает. Он ломается в hr = CoCreateInstance() в компине.h, где hr = 858993460; Я не понимаю, что моя ThorDetectorSwitch.dll, которая вызывает COM-dll, отлично работает с другим приложением. Но в моем текущем приложении он генерирует исключения, такие как «CoInitialize() не был вызван». В значительной степени я добавил много CoInitialize() во многих местах. –

+0

Похоже, что вы вызываете 'CoCreateInstance' из потока, который не называется' CoInitialize'. В качестве простого тестового вызова 'CoInitialize', когда вы обрабатываете' DLL_THREAD_ATTACH' в точке входа DLL (DllMain). –

+0

Ошибка произошла после того, как я добавил CoInitialize (NULL) в DllMain(); Я не понимаю, как я могу это сделать ... как снова позвонить? –

1

Я согласен с тем, что предлагаю оставить такой 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 
}; 

Вы можете оставить экземпляр в начале основной() функции резьбы, и/или в области видимости пространства имен перед вашим другим статическим объектом, требующим COM.

Если вы решите против тех, кто хочет и оригинальная идея, в ThorDetectorSwitch добавить:

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

затем использовать его со списком инициализации:

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

настроить тип возвращаемого в случае необходимости. Еще раз, что он считается субоптимальным решением по сравнению с другими.

+0

Я пробовал код, который придерживается оригинальной идеи, но компилятор говорит, что c - незаявленный идентификатор. Я предполагаю, что ComIniter должен быть определен где-то где? –

+0

определяется в первом блоке сообщения ... и в какой строке это сказано? –

+0

Я перешел на приватный: static const GUID ComHelper (const GUID arg) {...}, он компилируется. Но тогда есть и другие исключения: at if (* pfbegin! = NULL) (** pfBeigin)(); ++ pfBegin; Это находится в crt0dat.c; Я даже не знаю, что это значит .... –

Смежные вопросы