Cant use VC ATL COM DLL method at VB project
Author |
Message |
Peter Kadle #1 / 19
|
 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 |
|
 |
Igor Tandetni #2 / 19
|
 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 |
|
 |
Peter Kadle #3 / 19
|
 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 |
|
 |
Igor Tandetni #4 / 19
|
 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 |
|
 |
MVP for II #5 / 19
|
 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 |
|
 |
Igor Tandetni #6 / 19
|
 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 |
|
 |
Peter Kadle #7 / 19
|
 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 |
|
 |
Igor Tandetni #8 / 19
|
 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 |
|
 |
Craig Power #9 / 19
|
 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 |
|
 |
Alexander Nickolo #10 / 19
|
 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 |
|
 |
Craig Power #11 / 19
|
 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 |
|
 |
Alexander Nickolo #12 / 19
|
 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 |
|
 |
Peter Kadle #13 / 19
|
 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 |
|
 |
Igor Tandetni #14 / 19
|
 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 |
|
 |
Peter Kadle #15 / 19
|
 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 |
|
|
Page 1 of 2
|
[ 19 post ] |
|
Go to page:
[1]
[2] |
|