平台,框架&库
现在阅读
Dynamic Structures
0

Dynamic Structures

由 ultracpy2018年1月27日

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

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.  

'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

出处:https://www.codeproject.com/Articles/29675/Dynamic-Structures

关于作者
ultracpy
评论

你必须 登录 提交评论