Introduction
Some times we need to save memory pointed by the pointer variable rather than the pointer variable itself, i.e., memory allocated on heap. For example, when we create an object (which is not derived from CObject
) on the heap and we want to serialize the object, or we allocate some memory either using C / C++ memory allocation routines (malloc
, calloc
, or new
) or Windows API functions (GlobalAlloc
, HeapAlloc
, VirtualAlloc
etc.).
The MFC serialization architecture doesn't provide any explicit mechanism to save memory pointed by a pointer variable of an object of a class which is not derived from CObject
. If the pointer is an object of a class which is derived from CObject
or CString
, it can be serialized. But if it is a char *
, can it be serialized? Most probably, it can't be. That is why I present this article to solve the problem. This article is for adding serialization to non-CObject
derived classes, i.e., Object Persistence in MFC even for non-CObject
derived class objects.
Background
The basic ideas behind this is that you will first need to save the size of memory by using the following function:
void CArchive::WriteCount(DWORD_PTR dwCount);
Now, let's save the memory pointed by the pointer variable by using the following function:
void CArchive::Write(const void* lpBuf, UINT nMax);
Now, in the case of restoring back, you will first need to read the size of memory pointed by the pointer variable by using the following function:
DWORD_PTR CArchive::ReadCount();
Then you will need to read the memory content by using the following function:
UINT CArchive::Read(void* lpBuf, UINT nMax);
Using the code
Using the above basic ideas, you can make the following two utility functions:
void WritePointer(CArchive& ar, const void* lpBuf, UINT nMax);
void ReadPointer(CArchive& ar, void*& lpBuf, UINT& nMax);
Implementation of the above functions is given below:
void WritePointer(CArchive& ar, const void* lpBuf, UINT nMax)
{
ar.WriteCount(nMax);
ar.Write(lpBuf, nMax);
}
void ReadPointer(CArchive& ar, void*& lpBuf, UINT& nMax)
{
ASSERT(lpBuf == NULL);
nMax = UINT(ar.ReadCount());
lpBuf = malloc(nMax);
UINT nBytesRead = ar.Read(lpBuf, nMax);
if (nBytesRead != nMax)
{
AfxThrowArchiveException(CArchiveException::endOfFile);
}
}
Let's now use the above functions:
CPointerSerializationDoc::CPointerSerializationDoc(): m_buf(NULL)
{
wchar_t String[] = _T("This is the initialized value in m_buf.");
UINT nMax = sizeof(String);
m_buf = malloc(nMax);
memcpy_s(m_buf, nMax, String, nMax);
}
void CPointerSerializationDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
WritePointer(ar, m_buf, nMaxCount);
}
else
{
UINT nMaxCount = 0;
ReadPointer(ar, m_buf, nMaxCount);
}
}
History
- Nov. 8, 2007 - Article created.