65.9K
CodeProject 正在变化。 阅读更多。
Home

动态结构

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.40/5 (7投票s)

2008年9月25日

CPOL

1分钟阅读

viewsIcon

22719

downloadIcon

113

分配一个内存, 其中包含带有适当填充的变量


源代码

介绍  

在编写一些网络应用程序时,我们需要以字节数组的形式传递数据。我们可以通过简单地将数据指针转换为字节数组,然后通过网络发送这些数据来实现。当完全在 c/c++ 环境中工作时,这似乎很简单,但当涉及到只有少数数据类型可供选择的 com 对象时,它就成了一项艰巨的任务。

在这里,我介绍一种在运行时构建结构格式的技术

背景  

我的代码将变量对齐到内存中以形成特定结构的基础是基于微软编译器应用的填充规则。

规则 1. 结构的尺寸是结构中最大的本机数据类型的尺寸的倍数,例如(在 char、int 和 short int 中,int 是最大的尺寸)。

规则 2. 本机数据类型的结构成员变量将在数据类型尺寸的倍数的偏移量处。

规则 3. 在嵌入式结构的情况下,偏移量将是嵌入式结构中最大的本机数据类型尺寸的倍数。

使用代码

将变量对齐到内存中的主要函数如下进行:

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

我使用 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  

兴趣点 

当我将 GetCharArray 返回的变量分配给另一个变量时,我在 vbscript 中遇到了运行时错误。因此,我直接使用了该变量,而没有对其进行复制。目前正在寻找解决此问题的方法。

更多信息请访问 http://techxperts.info

历史

© . All rights reserved.