Passing DYNAMIC Data QUICKLY using SafeArrays - 2 | CodeGuru

Passing DYNAMIC Data QUICKLY using SafeArrays – 2

This builds upon the information given by Aravid Corera in his article "Using a Multidimensional SAFEARRAY to pass data across from COM objects." It replaces Richard Warg’s article "Using a BSTR to Transport C++ Objects Across the DCOM Interface." Although a creative idea, it is not a good idea to use BSTR for things other […]

Written By
CodeGuru Staff
CodeGuru Staff
Feb 14, 1999
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

This builds upon the information given by Aravid Corera in his article "Using a
Multidimensional SAFEARRAY to pass data across from COM objects." It replaces Richard
Warg’s article "Using a BSTR to Transport C++ Objects Across the DCOM
Interface." Although a creative idea, it is not a good idea to use BSTR for
things other than text.

This code shows how to pass data of any byte specific size, which may or may not be
known until runtime, through a SafeArray. This often occurs with data such as
bitmaps, binary files, or sound data. These are considered dynamic data because their size
and content can change from one session to another. Furthermore, it shows how to do
it as quick as possible. It also shows how to pack data from different variables
into the single array. The examples given are designed to be used in C++.
Other languages may or may not be able to determine the information packed into the array.

The first example uses memcpy() to copy the data directly into the SafeArray data.
This way is safe across all (D)COM processes, because it uses the standard COM
marshaller once the data is passed to the caller. The reason for using memcpy() is
speed. Calling SafeArrayPutElement() and SafeArrayGetElement() can get really slow.
Imagine calling them 2048 times( when getting and retrieving the data ) for a 1kb
file. COM is slow enough, no more overhead is needed.

The second example just passes a pointer to an area of memory that contains the data
needed. This is ONLY safe when using INPROC DLLs. I included this as more of
an example on how to past data as fast as possible, not necessarily the best and safest
way.

Example 1:

The SafeArray is created based on the total size of the data. Next we get access
to the data directly. Finally, using memcpy() the data is just transferred right
into the array.
Unpacking the data is pretty much exactly the reverse. The demo project and source
code shows how to do it. Notice that the header is passed in first, then using
pointer arithmetic, the bitmap bits are passed in.

HRESULT __stdcall CCOMDynamicData::PassBitmapCopy(LPSAFEARRAY* ppsaDynamic)
{
	long lBmpSize;
	if ( !m_bmp.bmBits )
	{
		lBmpSize = LoadDDBitmap();
		if ( lBmpSize == 0 )
		return S_FALSE;
	}
	else
		lBmpSize = m_bmp.bmWidthBytes * m_bmp.bmHeight;
	// Create the storage
	// notice the size is that of the header storage and of the bits
	SAFEARRAY* psaBitmapBits = ::SafeArrayCreateVector( VT_UI1, 0, sizeof(BITMAP ) + lBmpSize );
	LPVOID lpArrayData;
	::SafeArrayAccessData( psaBitmapBits, &lpArrayData );
	// copy the header
	::memcpy( lpArrayData, &m_bmp, sizeof( BITMAP ) );
	// copy the data
	// offset by the bitmap
	::memcpy( (char *)lpArrayData + sizeof( BITMAP ), m_bmp.bmBits,BmpSize );
	::SafeArrayUnaccessData( psaBitmapBits );
	*ppsaDynamic = psaBitmapBits;
	return S_OK;
}

Example 2:

Just pass a pointer to where the data is at. This is fast, but ONLY works in
INPROC servers. If you have no need for compatibility and will only be using INPROC
servers, then this is the way for you.

HRESULT __stdcall CCOMDynamicData::PassBitmapPtr(BITMAP* pBmp)
{
	if ( m_bmp.bmBits ) // if we already got the bitmap
	{
		*pBmp = m_bmp; // just return it
		return S_OK;
	}
	// else we gotta get bitmap information
	if ( LoadDDBitmap() == 0 )
		return S_FALSE;
	*pBmp = m_bmp;
	return S_OK;
}

The code in the zipped files below passes a bitmap structure between an INPROC COM
server and a client. Once the bitmap is retrived it is displayed on the screen.
Change the Bitmap in the COM DLL to demonstrate to yourself how the size of a
bitmap can be determined at runtime and then still have it’s data passed successfully.

Download demo project – 66 KB

Download source – 5 KB

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.