Error using array of structs from a COM-Dll

  • Thread starter Thread starter Michael
  • Start date Start date
M

Michael

Hi all,

I've written a COM-Dll (with ATL) that holds a database of marathon
runners. I wrote a function that returns the needed information of all
runners and it works fine in VB but not in VB.NET. I'm using an array
of structs as a return value. Here's the code of the function:

*************************************************

const IID ResultUDT_IID = {... };

STDMETHODIMP CDatabase::ResultAll(SAFEARRAY **pResult)
{
t_Result *Results = NULL;
ResultUDT *pData = NULL;

if (!m_bResult)
{
HRESULT hr = Error( _T("No result available!") );
return hr;
}

IRecordInfo *pUdtRecordInfo = NULL;
HRESULT hr = ::GetRecordInfoFromGuids(LIBID_SOFTLib, 1, 0, 0,
ResultUDT_IID, &pUdtRecordInfo );
if (FAILED(hr))
{
HRESULT hr2 = Error( _T("Can not create RecordInfo interface
for ResultUDT") );
return hr;
}

int RecordsCnt = MyDB->Cnt();
Results = My->Result;

SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = RecordsCnt ;

*pResult = ::SafeArrayCreateEx( VT_RECORD, 1, rgsabound,
pUdtRecordInfo );
pUdtRecordInfo->Release();
if (*pResult == NULL)
{
HRESULT hr2 = Error( _T("Can not create array of ResultUDT
structures") );
return hr2;
}

hr = ::SafeArrayAccessData(*pResult, (void**)&pData);
if (FAILED(hr))
return( hr );

for (int i=0; i<RecordsCnt; i++, pData++)
{
pData->Pnr = Results.pnr;
pData->Score = Results.Score;
CComBSTR bstrID = MyDB->PersonInfo[Results.tnr].ID;
bstrID.CopyTo(&pData->ID);
CComBSTR bstrFilepath = Results.Filepath;
bstrFilepath.CopyTo(&pData->Filepath);
}

hr = ::SafeArrayUnaccessData(*pResult);
return hr;
}

*************************************************

In the idl.-File I defined my struct as:

*************************************************

typedef
[uuid(...),
helpstring("Result Structure")]
struct ResultUDT
{
int Pnr;
int Score;
BSTR ID;
BSTR Filepath;
} ResultUDT;

*************************************************

and my interface looks like that:

*************************************************

interface INet : IDispatch
{
[id(1), helpstring("Result")]
HRESULT Result([out, retval] SAFEARRAY(struct ResultUDT)
*pResult);
}

*************************************************

In VB I can use that function and it works fine:

*************************************************

Dim res() as ResultUDT

....

res = DB.Result(5)

txtName.text = res(0).ID

*************************************************

In VB.NET I have written the following code (which somehow needs the
lib-name SOFTLib in front of the struct):

*************************************************

Dim res() as SOFTLib.ResultUDT

....

res = DB.Result(5)

txtName.text = res(0).ID

*************************************************

and that always brings up "System.IndexOutOfRangeException" because my
array "res" has the length 0.

Any ideas to this problem?

Thanks
Michael
 
Hi all,

I've written a COM-Dll (with ATL) that holds a database of marathon
runners. I wrote a function that returns the needed information of all
runners and it works fine in VB but not in VB.NET. I'm using an array
of structs as a return value. Here's the code of the function:

*************************************************

const IID ResultUDT_IID = {... };

STDMETHODIMP CDatabase::ResultAll(SAFEARRAY **pResult)
{
t_Result *Results = NULL;
ResultUDT *pData = NULL;

if (!m_bResult)
{
HRESULT hr = Error( _T("No result available!") );
return hr;
}

IRecordInfo *pUdtRecordInfo = NULL;
HRESULT hr = ::GetRecordInfoFromGuids(LIBID_SOFTLib, 1, 0, 0,
ResultUDT_IID, &pUdtRecordInfo );
if (FAILED(hr))
{
HRESULT hr2 = Error( _T("Can not create RecordInfo interface
for ResultUDT") );
return hr;
}

int RecordsCnt = MyDB->Cnt();
Results = My->Result;

SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = RecordsCnt ;

*pResult = ::SafeArrayCreateEx( VT_RECORD, 1, rgsabound,
pUdtRecordInfo );
pUdtRecordInfo->Release();
if (*pResult == NULL)
{
HRESULT hr2 = Error( _T("Can not create array of ResultUDT
structures") );
return hr2;
}

hr = ::SafeArrayAccessData(*pResult, (void**)&pData);
if (FAILED(hr))
return( hr );

for (int i=0; i<RecordsCnt; i++, pData++)
{
pData->Pnr = Results.pnr;
pData->Score = Results.Score;
CComBSTR bstrID = MyDB->PersonInfo[Results.tnr].ID;
bstrID.CopyTo(&pData->ID);
CComBSTR bstrFilepath = Results.Filepath;
bstrFilepath.CopyTo(&pData->Filepath);
}

hr = ::SafeArrayUnaccessData(*pResult);
return hr;
}

*************************************************

In the idl.-File I defined my struct as:

*************************************************

typedef
[uuid(...),
helpstring("Result Structure")]
struct ResultUDT
{
int Pnr;
int Score;
BSTR ID;
BSTR Filepath;
} ResultUDT;

*************************************************

and my interface looks like that:

*************************************************

interface INet : IDispatch
{
[id(1), helpstring("Result")]
HRESULT Result([out, retval] SAFEARRAY(struct ResultUDT)
*pResult);
}

*************************************************

In VB I can use that function and it works fine:

*************************************************

Dim res() as ResultUDT

...

res = DB.Result(5)

txtName.text = res(0).ID

*************************************************

In VB.NET I have written the following code (which somehow needs the
lib-name SOFTLib in front of the struct):

*************************************************

Dim res() as SOFTLib.ResultUDT

...

res = DB.Result(5)

txtName.text = res(0).ID

*************************************************

and that always brings up "System.IndexOutOfRangeException" because my
array "res" has the length 0.

Any ideas to this problem?

Thanks
Michael


You might want to post this to the interop group. You might get a
better answer there.
 
Back
Top