Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / ATL

Dynamic Structures

Rate me:
Please Sign up or sign in to vote.
1.40/5 (7 votes)
30 Mar 2010CPOL1 min read 22.1K   98   9   1
allocates a memory filled with the variable with appropriate padding

Source Code

Introduction  

When writing some network application we need to pass data in the form of byte array. that data we get from simply typecasting the  data pointer to the byte array and then we can send this over the network. This seems simple when working fully in the c/c++ environment but when it comes to com object where you have too few datatypes to choose from then it becomes a monumental task.  

Here I present a technique to build the structure format at run time

Background  

The basis of my code of aligning variables in to the memory to form a particular structure is based on padding rule which the microsoft compiler applies.

Rule 1. The size of the structure is in multiple of size of largest native data type available in the structure e.g. (in char, int and short  int is of the largest size) 

Rule 2. The structure member variable of native datatype will be at the offset which is in multiple of the size of the datatype  

Rule 3. In case of embedded structure, the offset will be in the multiple of size of largest native data type available in the embedded structure  

Using the code  

The main function of aligning the variables in to memory goes as following

C++
STDMETHODIMP CDynamicStructures::GetCharArray(VARIANT *pVarIn, long nSize, VARIANT *pVarOut)
{
	//Get the maximum size of native variable present in the list of input
	DWORD maxSize = GetMaxSize(pVarIn, nSize);
	//some thing wrong was present in the variant array
	if(maxSize == (DWORD)-1)	//Return Failure
		return S_FALSE;

	std::string str;
	//Allocate some initial size to string
	//increase it if necessary
	str.resize(maxSize * 100, '\0');

	DWORD dwSizeAllocated = 0;
	for(int i = 0; i < nSize; ++i)
	{
		DWORD size = GetSize(pVarIn[i]);
		int offset = dwSizeAllocated % size;
		//Apply Padding Rule. 2
		dwSizeAllocated += offset ? (size - offset) : 0;

		if(pVarIn[i].vt == VT_BSTR)	//Special case of string
		{
			std::string strData = (char *)_bstr_t(pVarIn[i]);
			int length = strData.size() + 1;
			memcpy((char*)str.c_str() + dwSizeAllocated, strData.c_str(), length);
			dwSizeAllocated += length;
		}
		else if(pVarIn[i].vt == VT_ARRAY)	//Special case of embedded structure
		{
			memcpy((char*)str.c_str() + dwSizeAllocated, pVarIn[i].parray->pvData, 
						pVarIn[i].parray->rgsabound[0].cElements);
			dwSizeAllocated += pVarIn[i].parray->rgsabound[0].cElements;
		}
		else
		{
			memcpy((char*)str.c_str() + dwSizeAllocated, &(pVarIn[i].bVal), size);
			dwSizeAllocated += size;
		}
	}

	//Apply Padding Rule. 1
	int offset = dwSizeAllocated % maxSize;
	dwSizeAllocated += offset ? (maxSize - offset) : 0;

	//Fill the value in array
	//Create safe array of 1 dimension 
	SAFEARRAY FAR* ppsa;
	unsigned int ndim =  1;
	//Allocate descriptor
	SafeArrayAllocDescriptor(ndim, &ppsa);

	(ppsa)->rgsabound[0].lLbound = maxSize;	//For internal purpose
	//this maxSize information will be used when embedding structures
	//in other structures
	(ppsa)->rgsabound[0].cElements = dwSizeAllocated;
	(ppsa)->cbElements = sizeof(char);
	
	//Allocate memory for the data
	SafeArrayAllocData(ppsa);
	memcpy(ppsa->pvData, str.c_str(), dwSizeAllocated);
	
	pVarOut->vt = VT_ARRAY;
	pVarOut->parray = ppsa;
	//Return Success
	return S_OK;
}

I have done the testing of my code with vbscript.  

VBScript
'Create Object
Set DynamicStructure = WScript.CreateObject("DynamicStructure.DynamicStructures")

'Create a structre of uchar, int, string of 45 characters, double, ushort
Dim data(5)
data(0) = DynamicStructure.GetUChar(5)
data(1) = DynamicStructure.GetInt(56)
data(2) = "hellohellohellohellohellohellohellohellohello"
data(3) = DynamicStructure.GetDouble(7.3452345)
data(4) = DynamicStructure.GetUShort(2345)

'create another structure of uchar, int, instance of previous structure,
'another instance of previous structure, string of 45 characters, double,
'ushort

Dim data1(7)
data1(0) = DynamicStructure.GetUChar(5)
data1(1) = DynamicStructure.GetInt(56)
data1(2) = DynamicStructure.GetCharArray(data(0), 5)
data1(3) = DynamicStructure.GetCharArray(data(0), 5)
data1(4) = "hellohellohellohellohellohellohellohellohello"
data1(5) = DynamicStructure.GetDouble(7.3452345)
data1(6) = DynamicStructure.GetUShort(2345)

'Allocate memory of for the structure by passing the array pointer and size of
'the array
dynSt3 = DynamicStructure.GetCharArray(data1(0), 7)
'Use the structure in whatever way you like
DynamicStructure.UseStructure dynSt3

'Release the memory
DynamicStructure.ReleaseCharArray dynSt3
DynamicStructure.ReleaseCharArray data1(2)
DynamicStructure.ReleaseCharArray data1(3)


Set DynamicStructure  = Nothing  

Points of Interest 

I was getting runtime error in vbscript when assigning the variable returned by GetCharArray to another variable. so i directly used the variable without making a copy of that. Currently in search of fix to this problem

For more information visit http://techxperts.info

History

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Applied Research Internation
India India
B. Tech + M. Tech in Chemical Engineering Smile | :) from IIT Delhi

Comments and Discussions

 
GeneralMy vote of 1 Pin
SledgeHammer0130-Mar-10 10:07
SledgeHammer0130-Mar-10 10:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.