Passing DYNAMIC Data QUICKLY using SafeArrays - 2


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

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;
		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


  • need some help

    Posted by Legacy on 12/16/2002 08:00am

    Originally posted by: buddie

    the return safe array contains

  • There is a memory leak i cannot find... Please help.

    Posted by Legacy on 10/22/2001 07:00am

    Originally posted by: Yoni Ribalsky


    I using your code in order to transfer images from server to the client and got huge urgent problem. Please help.

    As you can see server function does not cleaning up the SAFEARRAY and not freeing the memory since this memory should be transfered by mashaler to the client.

    And client are the one who making call to SafeArrayDestroy.
    I have created small program that transfering images every 40ms from server to client (PAL Video).

    The problem is that there is a memory leak in the PassBitmapCopy. The requirements for the memory are larger every 1 sec.

    Please help...

  • Cool Code !!! I have requrement of storing it in SQL

    Posted by Legacy on 11/11/2000 08:00am

    Originally posted by: Som

    I would like to store a BITMAP in the Database ....How should I go about it ?

  • Passing DYNAMIC Data QUICKLY using SafeArrays - 2

    Posted by Legacy on 10/26/1999 07:00am

    Originally posted by: Chris Nolan

    Question! I have a structure called DOG, with CString, Booleans, and Int's. I want to retrieve many records of type DOG in my structure and create SafeArray to pass (ALL the Records) back to the client at once. I need a dynamiclly SafeArray where each element in the array is a binary structure of the DOG data, and I need to know the simpliest way to covert the data in my Struct DOG to Binary!
    Can you help?

  • A simpler way to do this with IDL

    Posted by Legacy on 02/15/1999 08:00am

    Originally posted by: Gunnar Roth

    A simpler way to accomplish that task is to use IDL's size_is qualifier.

    interface IWhatSoEver : IUnknown
    [helpstring("method PassData")] HRESULT PassData([in, size_is(dwCount)] const BYTE* pDATA, [in] DWORD dwCount);

    size_is tells the marshaller,
    which parameter is used to indicate the size of the array
    pDATA points to.

    This may not work with other languages than C/C++. Dont know.

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date