URGENT : Passing SAFEARRAY of UDT from ATL DLL to VB 
Author Message
 URGENT : Passing SAFEARRAY of UDT from ATL DLL to VB

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



Sun, 06 Feb 2005 10:02:14 GMT  
 
 [ 1 post ] 

 Relevant Pages 

1. Passing UDT to C DLL from VB

2. How to pass a SafeArray to a dll

3. Passing Multi-dimensional SAFEARRAY from VB6 to VC++6 DLL

4. UDT and SAFEARRAY

5. How to pass array of UDT into DLL?

6. Calling C DLL from VB6: Passing an array of UDT

7. Passing UDT ByRef to DLL function changes its address

8. passing an array of UDT to a DLL

9. Length of UDT passed to C-DLL

10. When to Use ATL over VB for Component Development.(Very Urgent)

11. Passing UDT to Active DLL function

12. How to pass array of UDT into DLL?

 

 
Powered by phpBB® Forum Software