(Ох, как вспомню как я бился с dll'ками, статически линкуемыми с MFC, страшно становиться).
Теперь немного по делу. Если ты принимаешь правила framework'а. то принимаешь их полностью. Поэтому, если тебе говорят, что переключать контексты надо во всех экспортируемых, то надо их переключать. А иначе придется делать заключения ореализацииклассов famework'а (так как ты, безусловно корректно, сделал для CString), что не всегда возможно, особенно, если хост и dll'ка собраны с разными версиями билдами MFC (не говоря уже о разных версиях).
Но это все баблинг (и наверное, void, все-таки не для тебя, а для менее искушенных). А что касается непосредственно AFX_MODULE_STATE, то если не ошибаюсь он хранит только инфу, необходимую для mfc'овых хуков - любые функции dll, создающие окна, например те, которые работают с mfc'овыми CAsyncSocket'ами (отгадайте почему :), должны переключить контекст -, и что-то там с DAO.
Здравый же смысл, действительно подсказывает, что тривиальные функции, неимеющие сношений с MFC не должны переключать контекст модулей (операция, прямо скажем сама по себе нетривиальная). Но опять-таки подчеркну свое imho (входящее в резонанс с mfc'овым ho) - если framework навязывает - надо выполнять. Это как с параметрами операций типа IUnknown - можно AddRef не делать - и так работать будет, но это уже отклонение от стандарта, и вся ответственность лежит уже на вас.
Возможно, из-за недостатка моего опыта вопрос покажется очень простым,
но прошу не отсылать к MSDN. Там я не нашёл однозначного ответа «на все случаи жизни».
Вопрос в том, собственно, а всегда ли необходимо использовать этот макро в Regular DLL MFC?
1) DLL изготавливается не с «uses the shared MFC libraries», a «statically linked MFC».
Есть подозрение, что в этом случае AFX_MANAGE_STATE не нужен вовсе. Так ли?
2) Практически во всех статьях MSDN сказано, что если «shared MFC libraries», то используйте AFX_MANAGE_STATE во всех экспортируемых функциях (я бы поправил здесь писателей от мелкософт – не экспортируемых, а вызываемых).
Но так ли?
Положим, есть класс в «Regular DLL MFC whis shared MFC libraries»:
Четыре функции в конце декларации класса CI_ODBCquery доступны программисту для вызовов после «загрузки» DLL, т.е. программист вызывает эти функции DLL непосредственно.
Функция CanErrorMessage(const int can_msg) совсем простая. Она устанавливает msgerror в true/false:
Здесь, как бы и самое место тому AFX_MANAGE_STATE, поскольку речь идёт об непосредственном обращении к объекту error класса MFC CString. Но!!! Переменная error была инициализирована, а потом возможно «перезаписана» неоднократно совершенно из других приват-функций класса CI_ODBCquery. Сомнительно, что и здесь следует использовать AFX_MANAGE_STATE. Так?
С функцией Connection (LPCTSTR ConnectionStr), см. выше, возможно дело чуть сложнее, поскольку из её тела происходит «перераспределение» памяти, используемой, переменной CString connection:
Казалось бы, что раз мы «напрямую» задействуем MFC CString «из вне», то наличие AFX_MANAGE_STATE просто обязательно. Но!!! Переменная connection была инициализирована пустой строкой в конструкторе CI_ODBCquery до того, как программист может сделать вызов Connection(….). Я могу сильно ошибаться, но, на мой взгляд, класс CString слишком «прост» для того, что бы необходима была «синхронизация неизвестно чего при помощи макро AFX_MANAGE_STATE.
3) Возможно, то, что ниже - просто моё брюзжание. Но, например, ЭТО (и подобное ему) просто раздражает:
Knowledge Base Articles BUG: Wincore.cpp Line 879 Assert When Using MFC Classes
Q192853
….
Visual C++ Concepts: Adding Functionality
Exported DLL Function Entry Points
….
….
AFX_MANAGE_STATE does not need to be put into every function in the DLL. For example, InitInstance can be called by the MFC code in the application without AFX_MANAGE_STATE because MFC automatically shifts the module state before InitInstance and then switches it back after InitInstance returns. The same is true for all message-map handlers. Regular DLLs actually have a special master window procedure that automatically switches the module state before routing any message.
Т.е., товарищи от мелкософт здесь и выше говорят, о том, что вообщем-то AFX_MANAGE_STATE не только не всегда следует использовать, но «просто так» - это ещё и вредно.
PS. Прошу подсказать мне, что же на самом деле происходит?
[C++] Это очень страшно.27.09.03 18:09 Автор: Tlo Статус: Незарегистрированный пользователь
(Ох, как вспомню как я бился с dll'ками, статически линкуемыми с MFC, страшно становиться).
Теперь немного по делу. Если ты принимаешь правила framework'а. то принимаешь их полностью. Поэтому, если тебе говорят, что переключать контексты надо во всех экспортируемых, то надо их переключать. А иначе придется делать заключения ореализацииклассов famework'а (так как ты, безусловно корректно, сделал для CString), что не всегда возможно, особенно, если хост и dll'ка собраны с разными версиями билдами MFC (не говоря уже о разных версиях).
Но это все баблинг (и наверное, void, все-таки не для тебя, а для менее искушенных). А что касается непосредственно AFX_MODULE_STATE, то если не ошибаюсь он хранит только инфу, необходимую для mfc'овых хуков - любые функции dll, создающие окна, например те, которые работают с mfc'овыми CAsyncSocket'ами (отгадайте почему :), должны переключить контекст -, и что-то там с DAO.
Здравый же смысл, действительно подсказывает, что тривиальные функции, неимеющие сношений с MFC не должны переключать контекст модулей (операция, прямо скажем сама по себе нетривиальная). Но опять-таки подчеркну свое imho (входящее в резонанс с mfc'овым ho) - если framework навязывает - надо выполнять. Это как с параметрами операций типа IUnknown - можно AddRef не делать - и так работать будет, но это уже отклонение от стандарта, и вся ответственность лежит уже на вас.
Ничего нового, конечно, но может поможет.
[C++] Это очень страшно.28.09.03 01:41 Автор: void <Grebnev Valery> Статус: Elderman