导出类的串行化
众所周知,要对类的实例化对象进行串行化操作就需要使这个类能够进行类型识别操作、动态创建操作和串行化操作。即需要包含下面这两个宏:
DECLARE_SERIAL(CMyClass)
IMPLEMENT_SERIAL(CMyClass,CObject,sc_no)
但作为导出类,光具备这两个条件还不够,这里因为:
(
1
)在从文件中读出类对象时,需要调用
CRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum)
函数。函数体如下:
……………………
// search app specific classes
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
for
(pClass = pModuleState->m_classList; pClass != NULL;
pClass = pClass->m_pNextClass)
{
if
(lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)
{
AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
return
pClass;
}
}
AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
#ifdef
_AFXDLL
// search classes in shared DLLs
AfxLockGlobals(CRIT_DYNLINKLIST);
for
(CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
pDLL = pDLL->m_pNextDLL)
{
for
(pClass = pDLL->m_classList; pClass != NULL;
pClass = pClass->m_pNextClass)
{
if
(lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)
{
AfxUnlockGlobals(CRIT_DYNLINKLIST);
return
pClass;
}
}
}
AfxUnlockGlobals(CRIT_DYNLINKLIST);
#endif
TRACE1(
"Warning: Cannot load %hs from archive. Class not defined./n"
,
szClassName);
………………………………
Load()
函数的功能就是得到应用程序本身已经注册的类,并与当前文件中的类类型相比较,创建新的指定类型对象。这里的代码分为两部分:第一部分是从应用程序本身的注册类中进行查找,如果没有找到,则从注册的外部类(由动态链接库中导出的类)。如果还是没有找到,则返回
NULL
,提示“非预期的文件格式”。
(
2
)如果使用正常的
MFC
动态链接库,则导出类不会注册到应用程序的
AFX_MODULE_STATE
结构体中,也就是在应用程序初始化时动态链接库时不会初始化该动态链接库,,通过// search classes in shared DLLs也不会找到该类从而产生错误。因此,在此需要使用扩展的动态链接库,调用
DLLMain()
函数进行动态链接库的初始化操作。这样,程序才会正常进行串行化操作。