Hi,
I am using ATL DLLs on the business layer and VB for user
interface. These dlls are responsible for retrieving data
from the database depending upon the funmctionality. This
data is passed to VB in the form of SAFEARRAY.
As VB, i believe only supports single dimensional
SAFEARRAYS, hence UDTs can be used instead.
I am able to create such an array. But something seems to
be going wrong in populating data in it. I am attaching
my code below. Please tell me where exactly am I going
wrong.
Waiting for an early reply....
Regards
Shruti
**********************************************************
IDL FILE
**********************************************************
typedef
[uuid(BE094930-628F-4782-91CF-063EF1D7A118)]
struct BStruct
{
BSTR strID;
BSTR strDescr;
Quote:
} BStruct;
library RMLib
{ importlib("e:\hits\dlls\msado15.dll");
.....
interface IB : IDispatch
{
[id(1), helpstring("method GetList")] HRESULT GetList(
[in]_Connection* pConnect,
[out,retval]SAFEARRAY (BStruct)* pSaData);
};
.....
Quote:
};
**********************************************************
HEADER FILE
**********************************************************
STDMETHOD(GetList)(/*[in]*/_Connection* pConnect,
/*[out,retval]*/SAFEARRAY** pSaData);
**********************************************************
CPP FILE
**********************************************************
const IID BStruct_IID =
{ 0xBE094930, 0x628F, 0x4782,
{ 0x91, 0xCF, 0x06, 0x3E,
0xF1, 0xD7, 0xA1, 0x18
}
};
STDMETHODIMP CBuilding::GetList(_Connection *pConnect,
SAFEARRAY **pSaData)
{
HRESULT hr = S_OK;
if (pSaData == NULL)
{
*pSaData = NULL;
hr = S_FALSE;
return hr;
}
if (*pSaData != NULL)
*pSaData = NULL;
bstr_t strQuery("Select * from table");
_RecordsetPtr pRs = NULL;
_CommandPtr pCmd = NULL;
try
{
......
pRs = pCmd->Execute(NULL,NULL,adCmdText);
......
//Get Record Count in nRecCount of int datatype
......
LPTYPEINFO pTypeInfo = NULL;
LPTYPELIB pTypelib = NULL;
SAFEARRAYBOUND rgsabound;
rgsabound.lLbound = 0;
rgsabound.cElements = nRecCount;
BStruct* pstB = NULL;
IRecordInfo *pRecordInfo = NULL;
hr = LoadRegTypeLib(LIBID_RMLib, 1, 0,
GetUserDefaultLCID(), &pTypelib);
_ASSERT(SUCCEEDED(hr) && pTypeInfo);
hr = pTypelib->GetTypeInfoOfGuid(BStruct_IID,
&pTypeInfo);
_ASSERT(SUCCEEDED(hr) && pTypeInfo);
hr = GetRecordInfoFromTypeInfo(pTypeInfo,
&pRecordInfo);
_ASSERT(SUCCEEDED(hr) && pRecordInfo);
pTypeInfo->Release();
pTypelib->Release();
*pSaData = SafeArrayCreateEx(VT_RECORD,1,
&rgsabound,pRecordInfo);
pRecordInfo->Release();
_ASSERT(*pSaData);
hr = SafeArrayAccessData(*pSaData,
reinterpret_cast<PVOID*>(&pstB));
_ASSERT(SUCCEEDED(hr) && pstB);
long i = 0;
while (false == pRs->adoEOF)
{
pstB[i].strID = ::SysAllocString(pRs->Fields
->GetItem("id")->GetValue().bstrVal);
::SysFreeString(pstB[i].strID);
pstB[i].strDescr = ::SysAllocString(pRs->
Fields->GetItem("descr")->GetValue().bstrVal);
::SysFreeString(pstBuilding[i].strDescr);
i += 1;
pRs->MoveNext();
}
hr = SafeArrayUnaccessData(*pSaData);
_ASSERT(SUCCEEDED(hr));
hr = S_OK;
}
catch(...)
{
*pSaData = NULL;
hr = S_FALSE;
}
return hr;
Quote:
}
**********************************************************
VB CODE TO ACCESS THE ARRAY
**********************************************************
include the library in references n use the following
code on the click of a button:
Dim objATL As RMLib.B
Set objATL = New RMLib.B
Dim pData() As BStruct
Dim i, k As Integer
Dim pStruct As BStruct
pData = objATL.GetList(pConnection)
k = UBound(pData)
For i = 0 To k
pStruct = pData(i)
msgbox pStruct.strID & pStruct.strDescr
Next i
Set objtATL = Nothing