至今我们还没有涉及到客户部分的操作,现在就讨论一下。客户端通过调用服务器端的GetArray()方法来开始整个处理。客户端将会接收我们在服务器创建的安全对象。客户端的程序则负责将这块字节流变成为一个有效的C++对象。以下摘录了做这部分工作的客户端代码:
// create COM smart pointer from CLSID string
IBlobDataPtr pI( "TestServer.BlobData.1" );
SAFEARRAY *psa ;
// Get the safearray from the server
pI->GetArray( &psa );
file:// create a pointer to an object
CSimpleObj *dummy=NULL;
file:// blob object to eXPand
CBlob blob;
file:// use the blob to expand the safearray into an object
blob.Expand( (CObject*&)dummy, psa );
file:// call a method on the object to test it
dummy->Show(this->m_hWnd, "Client Message");
// delete the object
delete dummy;
这段代码挺简单的。它使用一个COM智能指针与服务器进行连接。如果你对智能指针不熟悉,这些方便的小对象通过调用CoCreateInstance()就可做所有的工作,与服务器进行连接。
CBlob类再一次完成这个步骤,这个类与服务器端的那一个是完全相同的。该类代码事实上是由服务器工程中得到的。将一个安全数组变成一个CSimpleObject的工作由Expand()方法完成。该方法与服务器端调用的Load()方法是相对的。
// Re-create an object from a SAFEARRAY
BOOL CBlob::Expand(CObject * &rpObj, SAFEARRAY *psa)
{
CMemFile memfile; // memory file for de-serialize
long lLength; // number of bytes
char *pBuffer; // buffer pointer
file:// lock Access to array data
SafeArrayAccessData( psa, (void**)&pBuffer );
// get number of elements in array. This is the number of bytes
lLength = psa->rgsabound->cElements;
// attach the buffer to the memory file
memfile.Attach((unsigned char*)pBuffer, lLength);
file:// start at beginning of buffer
memfile.SeekToBegin();
file:// create an archive with the attached memory file
CArchive ar(&memfile, CArchive::loadCArchive::bNoFlushOnDelete);
// document pointer is not used
ar.m_pDocument = NULL;
file:// inflate the object and get the pointer
rpObj = ar.ReadObject(0);
// close the archive
ar.Close();
file:// Note: pBuffer is freed when the SAFEARRAY is destroyed
file:// Detach the buffer and close the file
pBuffer = (char*) memfile.Detach();
file:// release the safearray buffer
SafeArrayUnaccessData( psa );
return TRUE;
}
这个方法的大部分代码你也在前面见过了,该方法接收一个安全数组的输入。我们由安全数组中取出缓冲的数据。CArchive对象负责将缓冲的数据重新创建为对象。
以下就是我们在刚才的Expand()方法中完成的事情
1、锁定访问安全数组结构,并且得到它的长度(以字节计)。
2、将安全数组的数据缓冲与一个CMemFile关联
3、将CMemFile与一个archive相关联
4、使用Archives的ReadObject()方法重新创建对象
5、将SAFEARRAY的数据缓冲由CMemFile脱离
6、返回一个指向新创建对象的指针给调用者
我们在这里谈到了许多基层的东西。CBlob类负责串行化和还原对象的繁重工作。COM部分的程序确实是很易懂的。