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)
{
DWORD maxSize = GetMaxSize(pVarIn, nSize);
if(maxSize == (DWORD)-1) return S_FALSE;
std::string str;
str.resize(maxSize * 100, '\0');
DWORD dwSizeAllocated = 0;
for(int i = 0; i < nSize; ++i)
{
DWORD size = GetSize(pVarIn[i]);
int offset = dwSizeAllocated % size;
dwSizeAllocated += offset ? (size - offset) : 0;
if(pVarIn[i].vt == VT_BSTR) {
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) {
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;
}
}
int offset = dwSizeAllocated % maxSize;
dwSizeAllocated += offset ? (maxSize - offset) : 0;
SAFEARRAY FAR* ppsa;
unsigned int ndim = 1;
SafeArrayAllocDescriptor(ndim, &ppsa);
(ppsa)->rgsabound[0].lLbound = maxSize; (ppsa)->rgsabound[0].cElements = dwSizeAllocated;
(ppsa)->cbElements = sizeof(char);
SafeArrayAllocData(ppsa);
memcpy(ppsa->pvData, str.c_str(), dwSizeAllocated);
pVarOut->vt = VT_ARRAY;
pVarOut->parray = ppsa;
return S_OK;
}
I have done the testing of my code with vbscript.
Set DynamicStructure = WScript.CreateObject("DynamicStructure.DynamicStructures")
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)
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)
dynSt3 = DynamicStructure.GetCharArray(data1(0), 7)
DynamicStructure.UseStructure dynSt3
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