COM+ Programming A Practical Guide Using Visual C++ and ATL [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

COM+ Programming A Practical Guide Using Visual C++ and ATL [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Memory Management



We have already covered how directional attributes dictate the role of the client and the server for memory management. To recap:





For an [in] parameter, the memory is allocated and freed by the client.





For an [out] parameter, the memory is allocated by the server and freed by the client.





For an [in, out] parameter, the memory is allocated by the client, freed by the server, allocated once again by the server, and finally freed by the client. If possible, the two server-side operations can be combined as one reallocation action.





Memory management APIs are:





SysAllocString, SysReAllocString, SysFreeString, etc. for BSTRs.





VariantInit and VariantClear for VARIANTs.





CoTaskMemAlloc, CoTaskMemReAlloc, and CoTaskMemFree for raw memory.





To demonstrate the use of memory management APIs, I will define two IDL structures; the first structure contains two BSTRs and a VARIANT, and the second structure contains an array of the first structure.



typedef struct tagMYLEADER {
BSTR bsFirstName;
BSTR bsLastName;
VARIANT vTitle;
}MYLEADER;
typedef struct tagMYLEADERS {
long lElements;
[size_is(lElements)] MYLEADER* pData;
}MYLEADERS;
// Interface method
HRESULT GetMyLeaders([out] MYLEADERS* pDataArray);


The following code fragment shows how the memory is allocated at the server side and deallocated at the client side:



// Server code
STDMETHODIMP CMyExplore::GetMyLeaders(MYLEADERS *pDataArray)
{
pDataArray->lElements = 2;
// raw allocation
pDataArray->pData =
(MYLEADER*) ::CoTaskMemAlloc(2 * sizeof(MYLEADER));
// BSTR allocations
pDataArray->pData[0].bsFirstName=SysAllocString(L"Mohandas");
pDataArray->pData[0].bsLastName=SysAllocString(L"Gandhi");
// BSTR allocation in VARIANT
VARIANT& v0 = pDataArray->pData[0].vTitle;
::VariantInit(&v0);
V_VT(&v0) = VT_BSTR;
V_BSTR(&v0) = ::SysAllocString(L"Mahatma");
// BSTR allocations
pDataArray->pData[1].bsFirstName=SysAllocString(L"Winston");
pDataArray->pData[1].bsLastName=SysAllocString(L"Churchil");
// BSTR allocation in VARIANT
VARIANT& v1 = pDataArray->pData[1].vTitle;
::VariantInit(&v1);
V_VT(&v1) = VT_BSTR;
V_BSTR(&v1) = ::SysAllocString(L"Sir");
return S_OK;
}
// Client code fragment
MYLEADERS leaders;
HRESULT hr = pMyExplore->GetMyLeaders(&leaders);
...
// Free memory
for(i=0; i<leaders.lElements; i++) {
MYLEADER* pLeader = &leaders.pData[i];
::VariantClear(&pLeader->vTitle); // freed BSTR in the variant
::SysFreeString(pLeader->bsFirstName); // freed BSTR
::SysFreeString(pLeader->bsLastName); // freed BSTR
}
::CoTaskMemFree(leaders.pData);
// freed raw allocation


The above code fragment used raw APIs for BSTRs and VARIANTs. To make the code less susceptible to human errors, one can use wrapper classes such as CComBSTR and CComVariant provided by ATL.



/ 125