Вопрос в том, собственно, а всегда ли необходимо использовать этот макро в 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»:
Код: Выделить всё
class CI_ODBCquery: public IQueryInterface
{
private:
CRecordset* Query;
…
…
CString connection;
CString error;
LPCTSTR error2;
bool msgerror;
public:
void __stdcall Connection (LPCTSTR ConnectionStr);
void __stdcall CanErrorMessage(const int can_msg);
void __stdcall ErrorMessage (LPTSTR* outval );
void __stdcall ErrorMessage2 (LPTSTR* outval );
…
…
};
Функция CanErrorMessage(const int can_msg) совсем простая. Она устанавливает msgerror в true/false:
Код: Выделить всё
void __stdcall CI_ODBCquery::CanErrorMessage(const int can_msg)
{
msgerror = can_msg ? true:false;
}
Функция ErrorMessage2(LPTSTR* outval ) – не сложнее. Она только «возвращает» указатель на нуль-терминированную строку error2:
Код: Выделить всё
void __stdcall CI_ODBCquery::ErrorMessage2(LPTSTR* outval)
{
*outval = error2;
}
Функция ErrorMessage(LPTSTR* outval ) – чуть «сложнее». Она «возвращает» указатель на нуль-терминированную строку – буфер класса MFC CString error:
Код: Выделить всё
void __stdcall CI_ODBCquery::ErrorMessage1(LPTSTR* outval)
{
*outval = (LPTSTR)((LPCTSTR)error);
}
С функцией Connection (LPCTSTR ConnectionStr), см. выше, возможно дело чуть сложнее, поскольку из её тела происходит «перераспределение» памяти, используемой, переменной CString connection:
Код: Выделить всё
void __stdcall CI_ODBCquery::Connection(LPCTSTR ConnectionStr)
{
connection = _TEXT("DSN=");
connection += ConnectionStr;
connection += _TEXT(";UID=;PWD=");
…
…
}
3) Возможно, то, что ниже - просто моё брюзжание. Но, например, ЭТО (и подобное ему) просто раздражает:
Knowledge Base Articles BUG: Wincore.cpp Line 879 Assert When Using MFC Classes
Q192853
….
Код: Выделить всё
STDMETHODIMP CTest::TestMethod()
{
[b]AFX_MANAGE_STATE(afxGetStaticModuleState()) [/b]
CDatabase db;
db.OpenEx("DSN=LocalServer;Database=pubs;UID=sa;PWD=;");
db.Close();
return S_OK;
}
Или ещё смешнее:
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. Прошу подсказать мне, что же на самом деле происходит?