Cant use VC ATL COM DLL method at VB project 
Author Message
 Cant use VC ATL COM DLL method at VB project

Ive built an ATL simple object class into my ATL COM
project. At the working area I selected the context menu
entry "Insert method ...". At the following dialog I
entered at name of method "Aktualisieren" and at
parameter "in] BSTR *ServerName, [in] BSTR *TableName,
[in] BSTR **FieldName, [in] int TableCount, [in] int
*FieldCount".

The single pointers are for one dimensional string arrays
and the dual pointer is for a two dimensional string array.

I already tested BSTR as correct type for VC, when VB uses
string (also implemented a few other methods which uses
one BSTR as parameter and thos worked fine).

When I include that DLL into my VB project, all methods
including Aktualisieren are offered by VB.

Wenn ich nun dieses DLL in ein VB Projekt einbinde, werden
mit alle Methoden inkl. Aktualisieren angeboten.

The variables at VB are declared the following way :
Dim ServerName() As String
Dim TableName() As String
Dim FieldName() As String
Dim TableCount As Integer
Dim FieldCount() As Integer

I ReDim them later (but indeed before I call the
method ;) ) cause neither the size of the one dimensional
arrays nore of the two dimensional array is fixed.

When I try to implement the method the following way

MyInt.Aktualisieren ServerName, TableName, FieldName,
TableCount, FieldCount

into the VB source the editor syntax check doesnt have any
prob at all (BTW a little strange is the fact, that if i
enter a brace after "MyInt.Aktualisieren" VB doenst offer
any parameter description at all (it does so with the
other methods)).

But at compile time I get the following error message at
the line quoted above :

compile error :
function or interface couldnt be used unlimited or its
usin some type of automation which isnt supported by
Visual Basic.

So wheres the problem with this method ? I tried in the
meantime to change the method description at the function
header at the .cpp, at the implementation at the .h and
finally also at the .idl to

[in] BSTR ServerName[], [in] BSTR TableName[], [in] BSTR
FieldName[][], [in] int TableCount, [in] int FieldCount[]

But that didnt worked, cause arrays need some counter as
limit. And when I entered TabeCount as counter it
mentioned that it needs fixed values.

And shouldnt be *var or var[] the same at C++ ? Or is
there some prob with usin one and/or two dimensional
string arrays as parameters for ATL/COM DLLs ?

Thx in advance for any hint on that topic.

cya, peter



Sun, 07 Aug 2005 23:31:55 GMT  
 Cant use VC ATL COM DLL method at VB project
You need to use SAFEARRAY to use arrays in automation compatible
interfaces, which is the kind of interface VB requires. You cannot use
conformant arrays (and you declare them incorrectly anyway). Also, BSTR
is already a pointer, you don't need extra level of indirection to pass
BSTRs as [in] parameters. Try this in your IDL file:

HRESULT Aktualisieren([in] BSTR serverName, [in] BSTR tableName,
    [in] SAFEARRAY(BSTR)* fieldNames, [in] int tableCount,
    [in] SAFEARRAY(int)* fieldCount);

In C++ implementation files, this becomes

HRESULT Aktualisieren(BSTR serverName, BSTR tableName,
    SAFEARRAY** ppFieldNames, int tableCount,
    SAFEARRAY** ppFieldCount);

You use SafeArray* family of API functions to work with safearrays.

Note: ATL Insert Method wizard does not support safearrays properly, it
will generate wrong prototype. You need to manually correct the method
in .idl, .h and .cpp files.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:
> Ive built an ATL simple object class into my ATL COM
> project. At the working area I selected the context menu
> entry "Insert method ...". At the following dialog I
> entered at name of method "Aktualisieren" and at
> parameter "in] BSTR *ServerName, [in] BSTR *TableName,
> [in] BSTR **FieldName, [in] int TableCount, [in] int
> *FieldCount".

> The single pointers are for one dimensional string arrays
> and the dual pointer is for a two dimensional string array.

> I already tested BSTR as correct type for VC, when VB uses
> string (also implemented a few other methods which uses
> one BSTR as parameter and thos worked fine).

> When I include that DLL into my VB project, all methods
> including Aktualisieren are offered by VB.

> Wenn ich nun dieses DLL in ein VB Projekt einbinde, werden
> mit alle Methoden inkl. Aktualisieren angeboten.

> The variables at VB are declared the following way :
> Dim ServerName() As String
> Dim TableName() As String
> Dim FieldName() As String
> Dim TableCount As Integer
> Dim FieldCount() As Integer

> I ReDim them later (but indeed before I call the
> method ;) ) cause neither the size of the one dimensional
> arrays nore of the two dimensional array is fixed.

> When I try to implement the method the following way

> MyInt.Aktualisieren ServerName, TableName, FieldName,
> TableCount, FieldCount

> into the VB source the editor syntax check doesnt have any
> prob at all (BTW a little strange is the fact, that if i
> enter a brace after "MyInt.Aktualisieren" VB doenst offer
> any parameter description at all (it does so with the
> other methods)).

> But at compile time I get the following error message at
> the line quoted above :

> compile error :
> function or interface couldnt be used unlimited or its
> usin some type of automation which isnt supported by
> Visual Basic.

> So wheres the problem with this method ? I tried in the
> meantime to change the method description at the function
> header at the .cpp, at the implementation at the .h and
> finally also at the .idl to

> [in] BSTR ServerName[], [in] BSTR TableName[], [in] BSTR
> FieldName[][], [in] int TableCount, [in] int FieldCount[]

> But that didnt worked, cause arrays need some counter as
> limit. And when I entered TabeCount as counter it
> mentioned that it needs fixed values.

> And shouldnt be *var or var[] the same at C++ ? Or is
> there some prob with usin one and/or two dimensional
> string arrays as parameters for ATL/COM DLLs ?

> Thx in advance for any hint on that topic.

> cya, peter



Mon, 08 Aug 2005 00:25:43 GMT  
 Cant use VC ATL COM DLL method at VB project
Quote:
>You need to use SAFEARRAY to use arrays in automation
compatible
>interfaces, which is the kind of interface VB requires.
You cannot use
>conformant arrays (and you declare them incorrectly
anyway). Also, BSTR
>is already a pointer, you don't need extra level of
indirection to pass
>BSTRs as [in] parameters. Try this in your IDL file:

>HRESULT Aktualisieren([in] BSTR serverName, [in] BSTR
tableName,
>    [in] SAFEARRAY(BSTR)* fieldNames, [in] int
tableCount,
>    [in] SAFEARRAY(int)* fieldCount);

>In C++ implementation files, this becomes

>HRESULT Aktualisieren(BSTR serverName, BSTR tableName,
>    SAFEARRAY** ppFieldNames, int tableCount,
>    SAFEARRAY** ppFieldCount);

>You use SafeArray* family of API functions to work with
safearrays.

>Note: ATL Insert Method wizard does not support

safearrays properly, it

Quote:
>will generate wrong prototype. You need to manually
correct the method
>in .idl, .h and .cpp files.

Hey Igor,

thx for your help. I know that BSTR is a pointer. But I
need 2 one dimensional arrays of BSTR elements and 1 two
dimensional array of BSTR elements. Thats why I used two
pointer on BSTR for the two dimensional array and one
pointer on BSTR at the one dimensional array. So is the
syntax of your IDL and CPP/H example still correct or do
i have to change "SAFEARRAY(...)*" to "SAFEARRAY(...)**"
for the two dimensional array of BSTR elements and
from "BSTR" to "SAFEARRAY(BSTR)*" for the one dimensional
array of BSTR elements ?

cya, peter



Mon, 08 Aug 2005 01:39:34 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:
> thx for your help. I know that BSTR is a pointer. But I
> need 2 one dimensional arrays of BSTR elements and 1 two
> dimensional array of BSTR elements. Thats why I used two
> pointer on BSTR for the two dimensional array and one
> pointer on BSTR at the one dimensional array. So is the
> syntax of your IDL and CPP/H example still correct or do
> i have to change "SAFEARRAY(...)*" to "SAFEARRAY(...)**"
> for the two dimensional array of BSTR elements and
> from "BSTR" to "SAFEARRAY(BSTR)*" for the one dimensional
> array of BSTR elements ?

Ah, I see. No, you need SAFEARRAY(BSTR)* everywhere. A safearray carries
the number of dimensions internally - see SafeArrayGetDim. Dimensions
are not represented by extra levels of indirection, unlike C arrays.

I think a 2d array is declared in VB as follows:

Dim FieldName(,) As String   ' note the comma between parens

I'm by no means a VB expert though.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Mon, 08 Aug 2005 03:09:28 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:


> > thx for your help. I know that BSTR is a pointer. But I
> the number of dimensions internally - see SafeArrayGetDim. Dimensions
> are not represented by extra levels of indirection, unlike C arrays.

> I think a 2d array is declared in VB as follows:

 'sample

Dim FieldName() As String    ' in C++ this would be SAFEARRAY *FieldName=
NULL;

Redim FieldNames(10,2) '11 elements, 2 dimensions

Quote:

> I'm by no means a VB expert though.
> --
> With best wishes,
>     Igor Tandetnik

> "For every complex problem, there is a solution that is simple, neat,
> and wrong." H.L. Mencken



Mon, 08 Aug 2005 16:40:11 GMT  
 Cant use VC ATL COM DLL method at VB project


Quote:
> Dim FieldName() As String    ' in C++ this would be SAFEARRAY
*FieldName=
> NULL;

> Redim FieldNames(10,2) '11 elements, 2 dimensions

You sure it does not create a 2d array with 33 elements (11 x 3)? I
think the number of dimensions is inferred from the number of
parameters, not explicitly specified as the last parameter.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Mon, 08 Aug 2005 22:50:56 GMT  
 Cant use VC ATL COM DLL method at VB project
Quote:
>*FieldName=
>> NULL;

>> Redim FieldNames(10,2) '11 elements, 2 dimensions

>You sure it does not create a 2d array with 33 elements
(11 x 3)? I
>think the number of dimensions is inferred from the
number of
>parameters, not explicitly specified as the last

parameter.

Hey Igor,

really hate this SafeArray stuff ;) . Got asome hint that
I have to use SAFEARRAY(BSTR var at the IDL file. That way
all the elements of the SafeArray structure were avail
(like cDims for example). But that way the parameters
still werent offered by VB.
Then I changed it to the way you posted here by entering
SAFEARRAY(BSTR)* var at the IDL. Amazing ... now for the
first time all three parameters were offered by VB :) .
Even with the correct String type.
But then my problems started at VC.
Ive done the following implementation at VC to access the
SafeArray elements of one of the three parameters.

BTW Learned in the meantime, that entering ReDim var
(0,whatever) is the same as ReDim (whatever) So its
detected automatically as one dimensional array (thats
useful, causeat the two dimensional array there are
sometimes just one row existent. So one dimensional would
be correct for this case). But here comes the strange
fact : When you use SafeArrayGetDim you get 2 (two !) as
return value for FieldName which I ReDimed using ReDim
FiledName (0,whatever). Thats one of many problems I
detected with that stuff. The others are part of the code :

--- begin of text ---

STDMETHODIMP CMyInte::Aktualisieren(SAFEARRAY
**ServerName, SAFEARRAY **TableName,

                SAFEARRAY **FieldName)

{
        AFX_MANAGE_STATE(AfxGetStaticModuleState())
        long i, j, k, l, start, end;
        j = SafeArrayGetDim(*FieldName);
        BSTR HUGEP *FieldData;
        SafeArrayAccessData(*FieldName, (void HUGEP* FAR*)
&FieldData);
        _bstr_t pfad;
        for (i=0;i<j;i++)
        {
                SafeArrayGetLBound(*FieldName, i+1,
&start);
                SafeArrayGetUBound(*FieldName, i+1, &end);
                for(k = start; k<end; k++)
                {
                        AfxMessageBox(FieldData[i][k]);
//                      l = i*(k+1);
//                      SafeArrayGetElement(*FieldName,
&l, &pfad);
//                      AfxMessageBox(pfad);
                }
        }
        return S_OK;

Quote:
}

--- end of text ---

The VB source looks like this :

--- begin of text ---

Dim FieldName as String
....
ReDim Preserve FieldName (0,9)
....
MyInt.Aktualisieren ServerName, TableName, FieldName

--- end of text ---

0 and 9 are the real values of some variables indeed ;) .

But I cant access the elements of the SafeArray at all
with the source above. And neither cant I directly access
the elements of the SafeArray structure (which I clearly
prefer isntead of using this SafeArray.... function) cause
SafeArray is implemented as pointer on pointer. So I can
neither access the elements of the structure by entring
FieldName-> nor by entering *FieldName-> :( .

Usually I get some hints from you and get the rest by
examinign MSDN. But MSDN seems to be a complete waste of
time on that topic :( . So is there some little example
anywhere were some simple stringarray is passed by some VB
app and then handled on the VC side (perhaps even one time
handling a one dimensional array of BSTR and the other
time handling a two dimensional one). There is some small
example at MSDN, but that one didnt work at all (cause
they using the structure elements directly, which doesnt
work for me as mentioned above).

So thx again,

peter



Tue, 09 Aug 2005 18:59:52 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:
> BTW Learned in the meantime, that entering ReDim var
> (0,whatever) is the same as ReDim (whatever)

You sure? I would expect it to create a 2d array with the dimensions of
1x(whatever+1). What makes you think those two statements produce the
same result?

Quote:
> So its
> detected automatically as one dimensional array (thats
> useful, causeat the two dimensional array there are
> sometimes just one row existent. So one dimensional would
> be correct for this case). But here comes the strange
> fact : When you use SafeArrayGetDim you get 2 (two !) as
> return value for FieldName which I ReDimed using ReDim
> FiledName (0,whatever).

This just proves that two ReDim statements are not equivalent after all.
The behavior you ovserve is consistent with my expectations.

Quote:
> Thats one of many problems I
> detected with that stuff. The others are part of the code :

FieldData[i][k] does not do what you think it does. It accesses k-th
character in i-th BSTR.

All elements in 2d safearray are packed into one memory block. If the
array is MxN, the elements are stored in the following order:

(0, 0), (1, 0), ..., (M-1, 0), (0, 1), (1, 1), ..., (0, N-1), (1, N-1),
..., (M-1, N-1)

Note that the order is reverse from how C/C++ arranges a 2d array in
memory.

The easiest way to enumerate all elements is as follows:

SAFEARRAY* psa;
UINT cDims = SafeArrayGetDim(psa);
int cElems = 1;
// dimensions are numbered from 1
for (int d = 1; d <= cDims; ++d)
{
    long lBound, uBound;
    SafeArrayGetLBound(psa, d, &lBound);
    SafeArrayGetUBound(psa, d, &uBound);
    cElems *= (uBound - lBound + 1);

Quote:
}

// Now we can just access the data as 1d array with cElems elements
// Remember the unusual ordering
BSTR* pData;
SafeArrayAccessData(psa, (void**)&pData);
for (int i = 0; i < cElems; ++i)
{
    DoSomething(pData[i]);
Quote:
}

SafeArrayUnaccessData(psa);

If you need to specifically access element (i, j), you need to calculate
the offset yourself as

ind = (i-lBound1) + (j - lBound2) * M

where lBound1 and lBound2 are lower bounds for corresponding dimensions,
M = (uBound1 - lBound1 + 1) is the number of elements in the first
dimension.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Wed, 10 Aug 2005 00:53:38 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:

> All elements in 2d safearray are packed into one memory block. If the
> array is MxN, the elements are stored in the following order:

> (0, 0), (1, 0), ..., (M-1, 0), (0, 1), (1, 1), ..., (0, N-1), (1, N-1),
> ..., (M-1, N-1)

> Note that the order is reverse from how C/C++ arranges a 2d array in
> memory.

SafeArrays are column-major?  That's cool.  Yet another case where VB
acts like fortran.  (There are a surprising number of similarities,
overall.)

--
Craig Powers
MVP - Visual C++



Wed, 10 Aug 2005 03:57:41 GMT  
 Cant use VC ATL COM DLL method at VB project
Were you surprised? Visual Basic is built on top of BASIC, and that has
been designed as a simplistic Fortran at the time... (I haven't been born
yet at that time...)

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD

MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

Quote:


> > All elements in 2d safearray are packed into one memory block. If the
> > array is MxN, the elements are stored in the following order:

> > (0, 0), (1, 0), ..., (M-1, 0), (0, 1), (1, 1), ..., (0, N-1), (1, N-1),
> > ..., (M-1, N-1)

> > Note that the order is reverse from how C/C++ arranges a 2d array in
> > memory.

> SafeArrays are column-major?  That's cool.  Yet another case where VB
> acts like Fortran.  (There are a surprising number of similarities,
> overall.)

> --
> Craig Powers
> MVP - Visual C++



Wed, 10 Aug 2005 06:18:01 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:



> > > All elements in 2d safearray are packed into one memory block. If the
> > > array is MxN, the elements are stored in the following order:

> > > (0, 0), (1, 0), ..., (M-1, 0), (0, 1), (1, 1), ..., (0, N-1), (1, N-1),
> > > ..., (M-1, N-1)

> > > Note that the order is reverse from how C/C++ arranges a 2d array in
> > > memory.

> > SafeArrays are column-major?  That's cool.  Yet another case where VB
> > acts like Fortran.  (There are a surprising number of similarities,
> > overall.)

> Were you surprised? Visual Basic is built on top of BASIC, and that has
> been designed as a simplistic Fortran at the time... (I haven't been born
> yet at that time...)

Considering the other similarities, I'm not surprised, but I didn't
know that already.

A number of the similarities go beyond the extent of FORTRAN 77, which
would I believe have been contemporary with the original BASIC.  VB
also has commonalities with some of the more common extensions that
made it into Fortran 9x.

--
Craig Powers
MVP - Visual C++



Wed, 10 Aug 2005 07:04:30 GMT  
 Cant use VC ATL COM DLL method at VB project
BASIC has been developed in 1968 IIRC, and the then current version
should be Fortran VI. Not that there are many new elements in
Fortran 77...

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD

MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

Quote:




> > > > All elements in 2d safearray are packed into one memory block. If the
> > > > array is MxN, the elements are stored in the following order:

> > > > (0, 0), (1, 0), ..., (M-1, 0), (0, 1), (1, 1), ..., (0, N-1), (1, N-1),
> > > > ..., (M-1, N-1)

> > > > Note that the order is reverse from how C/C++ arranges a 2d array in
> > > > memory.

> > > SafeArrays are column-major?  That's cool.  Yet another case where VB
> > > acts like Fortran.  (There are a surprising number of similarities,
> > > overall.)

> > Were you surprised? Visual Basic is built on top of BASIC, and that has
> > been designed as a simplistic Fortran at the time... (I haven't been born
> > yet at that time...)

> Considering the other similarities, I'm not surprised, but I didn't
> know that already.

> A number of the similarities go beyond the extent of FORTRAN 77, which
> would I believe have been contemporary with the original BASIC.  VB
> also has commonalities with some of the more common extensions that
> made it into Fortran 9x.

> --
> Craig Powers
> MVP - Visual C++



Wed, 10 Aug 2005 09:43:51 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:
>You sure? I would expect it to create a 2d array with the
dimensions of
>1x(whatever+1). What makes you think those two statements
produce the
>same result?

Cause 1 * whatever + 1 is a 1 dimensional array (as you
mentioned it contains only one "row".
But that prob aint the big one, cause I could catch the
first variable with some "if firstvar = 0 then redim
(whatever) else redim (firstvar, whatever) endif".

Quote:
>FieldData[i][k] does not do what you think it does. It
accesses k-th
>character in i-th BSTR.

>All elements in 2d safearray are packed into one memory
block. If the
>array is MxN, the elements are stored in the following
order:

>(0, 0), (1, 0), ..., (M-1, 0), (0, 1), (1, 1), ..., (0, N-
1), (1, N-1),
>...., (M-1, N-1)

>Note that the order is reverse from how C/C++ arranges a
2d array in
>memory.

>The easiest way to enumerate all elements is as follows:

>SAFEARRAY* psa;
>UINT cDims = SafeArrayGetDim(psa);
>int cElems = 1;
>// dimensions are numbered from 1
>for (int d = 1; d <= cDims; ++d)
>{
>    long lBound, uBound;
>    SafeArrayGetLBound(psa, d, &lBound);
>    SafeArrayGetUBound(psa, d, &uBound);
>    cElems *= (uBound - lBound + 1);
>}

>// Now we can just access the data as 1d array with
cElems elements
>// Remember the unusual ordering
>BSTR* pData;
>SafeArrayAccessData(psa, (void**)&pData);
>for (int i = 0; i < cElems; ++i)
>{
>    DoSomething(pData[i]);
>}
>SafeArrayUnaccessData(psa);

>If you need to specifically access element (i, j), you
need to calculate
>the offset yourself as

>ind = (i-lBound1) + (j - lBound2) * M

>where lBound1 and lBound2 are lower bounds for

corresponding dimensions,

Quote:
>M = (uBound1 - lBound1 + 1) is the number of elements in
the first
>dimension.

Sound interesting. But im not using a SAFEARRAY*, but
instead a SAFEARRAY** (rememeber the IDL implementation
SAFEARRAY(BSTR)* at IDL and therefor SAFEARRAY** at CPP/H.
So all this single pointer SAFEARRAY* examples are not
useful for this case). So how would this stuff work in
reality, means under the changed condition im using.
Already tried to typecast that stuff, but its impossible
to get any useful information out of a SAFEARRAY**.


Fri, 12 Aug 2005 18:37:39 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:
> >You sure? I would expect it to create a 2d array with the
> dimensions of
> >1x(whatever+1). What makes you think those two statements
> produce the
> >same result?

> Cause 1 * whatever + 1 is a 1 dimensional array (as you
> mentioned it contains only one "row".

No it is not. It's a 2d array with one dimension just happening to be 1.
You have to access the elements as MyArray(0, i), not MyArray(i) as you
would with 1d array. How you envision the array in your mind is
irrelevant, what's important is how the compiler and the run-time treats
it.

Quote:
> But that prob aint the big one, cause I could catch the
> first variable with some "if firstvar = 0 then redim
> (whatever) else redim (firstvar, whatever) endif".

Of course you can do that, but why would you want to? You'll just create
special cases for all your code to handle. A 2d array with one dimension
being 1 requires no special treatment, but with this logic, your server
has to be prepared to accept both 1d and 2d arrays.

Quote:
> Sound interesting. But im not using a SAFEARRAY*, but
> instead a SAFEARRAY** (rememeber the IDL implementation
> SAFEARRAY(BSTR)* at IDL and therefor SAFEARRAY** at CPP/H.

So? Is the code below so hard to figure out?

SAFEARRAY** ppsa; // comes as a parameter
SAFEARRAY* psa = *ppsa;
// Work with psa

--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Fri, 12 Aug 2005 22:56:18 GMT  
 Cant use VC ATL COM DLL method at VB project

Quote:
>All elements in 2d safearray are packed into one memory
block. If the
>array is MxN, the elements are stored in the following
order:

>(0, 0), (1, 0), ..., (M-1, 0), (0, 1), (1, 1), ..., (0, N-
1), (1, N-1),
>...., (M-1, N-1)

Hey Igor,

that one were really useful, cause I didnt knew that Vb
stores arrays that way into SafeArray elements.

Quote:
>SAFEARRAY* psa;
>UINT cDims = SafeArrayGetDim(psa);
>int cElems = 1;
>// dimensions are numbered from 1
>for (int d = 1; d <= cDims; ++d)
>{
>    long lBound, uBound;
>    SafeArrayGetLBound(psa, d, &lBound);
>    SafeArrayGetUBound(psa, d, &uBound);
>    cElems *= (uBound - lBound + 1);
>}

>// Now we can just access the data as 1d array with
cElems elements
>// Remember the unusual ordering
>BSTR* pData;
>SafeArrayAccessData(psa, (void**)&pData);
>for (int i = 0; i < cElems; ++i)
>{
>    DoSomething(pData[i]);
>}
>SafeArrayUnaccessData(psa);

>If you need to specifically access element (i, j), you
need to calculate
>the offset yourself as

>ind = (i-lBound1) + (j - lBound2) * M

>where lBound1 and lBound2 are lower bounds for

corresponding dimensions,

Quote:
>M = (uBound1 - lBound1 + 1) is the number of elements in
the first
>dimension.

That one were useful too. Worked that way almost
perfectly. Just cDims were the wrong variable for the
first loop, cause it only stores the account of the
dimensions and not the account of the rows. Neither is
there any SafeArray member which tells how much values are
stored at each row. So I build 2 new parameters. An array
of long called FieldCount whcih simply tells the valid
values per table. And TableCount which tells how many
tables are there (and replaces therefor cDims). And then I
had to handle the fact that your example used single
SAFEARRAY pointers, but I had to use pointer on SAFEARRAY
pointer. But then I remembered C basics (by building a
single pointer and setting it to the value of the pointer
on pointer). This is the source I used :

--- begin of text ---

STDMETHODIMP CMyInte::Aktualisieren(SAFEARRAY
**ServerName, SAFEARRAY **TableName,

                SAFEARRAY **FieldName, SAFEARRAY
**FieldCount, long TableCount)

{
        AFX_MANAGE_STATE(AfxGetStaticModuleState())
        SAFEARRAY *psa1 = *FieldName;
        SAFEARRAY *psa2 = *FieldCount;
        int cElems(1);
        for (int d = 1; d <= TableCount; ++d)
        {
                long lBound, uBound;
                SafeArrayGetLBound(psa1, d, &lBound);
                SafeArrayGetUBound(psa1, d, &uBound);
                cElems *= (uBound - lBound + 1);
        }
        BSTR *pData;
        long *pCount;
        SafeArrayAccessData(psa1, (void**)&pData);
        SafeArrayAccessData(psa2, (void**)&pCount);
        _bstr_t test;
        for (int i = 0; i < cElems; ++i)
                if (pCount[i % TableCount] > i /
TableCount)
                {
                        test = (_bstr_t)pData[i];
                        AfxMessageBox(test);
                }
        SafeArrayUnaccessData(psa1);
        SafeArrayUnaccessData(psa2);
        return S_OK;

Quote:
}

--- end of text ---

So thx a lot for your help,

peter



Fri, 12 Aug 2005 23:03:40 GMT  
 
 [ 19 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Problem using a VB COM object in ATL project

2. VC ATL DLL crashin with VB COM client

3. what is the diffrence between Activex DLL in VB and ATL COM in VC

4. Cant compile ATL COM AppWizard project

5. VB COM MIGRATION TO ATL VC COM

6. Problem with scripting context when using VB com object inside VC com object

7. problems passing ADO Recordset from VB-COM client to VC-COM-Server dll

8. Using VB collections in a VB DLL in VC

9. Accessing a collection from a VB com server in a VC/ATL Client

10. ATL COM Project with MFC Support causes problem with Processor Pack for VC.

11. how to call function in a DLL from ATL COM method

12. how to call function in a DLL from ATL COM method

 

 
Powered by phpBB® Forum Software