Solved

VB String Array ??? (up to 100 pts)

Posted on 2002-03-03
12
252 Views
Last Modified: 2010-04-01
Hi,

The background
--------------
I'm working on a project which is mainly written in VB, but makes use of various c++ components, for speed purposes.

My VB program makes use of multidimentional string arrays throughout the program, and one of the c++ utilities I've written passes back arrays of string (actually a variant array).

However, in my VB project I have to convert all my String() variables into variants and perform other conversion functions when passing these values into other functions (that expect a string as a parameter). Which seems to me to be negating the speed advantage I have of calling the c++ function in the first place.

The question
------------
Can I return a two dimentional string array back to VB from c++ using an ATL component ???

I've done this already using a safearray, passed back as a variant, but want to avoid this.

The answer
----------
If the answer is no, then the points remain at 25

If the answer is yes and you can tell me how, then I'll up the points to 100
0
Comment
Question by:smegghead
  • 5
  • 3
  • 3
  • +1
12 Comments
 
LVL 7

Expert Comment

by:peterchen092700
ID: 6837887
No, not without an safearray.


(Why do you think any other method would be easier?)
0
 
LVL 10

Author Comment

by:smegghead
ID: 6837978
It's more to avoid having to translate it back into a string at a later stage.

Basically I had written a component in VB, which passed an array back to the calling function. I've since re-written the component in c++, but can't return a string array.. so I've got to change all the calling code to use variants, which requires lots of code changes, and variable redefinitions.

0
 
LVL 10

Author Comment

by:smegghead
ID: 6837980
I would have thought that if a VB component can pass a string array back to another VB appliction using COM, then the interface can actually cope with it.
0
 
LVL 2

Accepted Solution

by:
christophm earned 25 total points
ID: 6838387
Hi smegghead,

Here is a way outlined (following this outline some gotchas)

1. Create a record (user defined type) in VB and put your strings (arrays of strings, integers, whatevers) in the user defined record.

2. Create a .H (include file) for your VC program that matches variable-for-variable the variables in the VB user defined type.

3. Write your C code in a DLL.  (When I use this method I have always done the DLL in C not C++, however, a shared DLL (MFC/C++ 'enabled') should work just fine).

4. Put a function in the DLL that takes a LPVOID* as parameter).

5. From VB call the function (define it first of course!) and pass the user defined record by address (ByRef).

This will work really swell - have done numerous DLLs for my VB buds using this method.

The GOTCHAs !

1. If you choose to to this I think you would stay away from 'fancy' data types and stick with the primitives in VB, Integers, Strings.  If you want to do VARIANTS it would work but your other answerers have described more appropriate (read standard) ways of handling VARIANTs between the two languages.

2. Use FIXED LENGTH STRINGS (String*9 for example) only in the user defined record type on the VB side.  This will make the VB stuff store the string without the prefix header specifying length and will make it truly appear as an 'array of characters' to the VC side.  BTW - I encourage my VB buds to put a CHR$(0) at the end of those fixed length strings.

3. For strings you are restricted to fixed length strings (or else you are back in VARIANT/BSTR land! - which you are asking to escape from).

3. VB and VC in the default mode may align various data types somewhat differently; i.e., ny experience has been that the two languages (VB V6 and VC V6) appear to insert slack bytes using different criteria.  (1) put the integers at the top of the user defined record type (2) put the strings next (3) change the C++ options to 2-byte (I recall the default is 4) alignment (4) run the DLL from a trial C caller and look at what the LPVOID* references and make sure the .H file in C matches - if it doesn't then change it.

if you want to pursue this approach and need more info say so here and I will dust off the archives and cut some code (VB and C) out and paste it here.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6838415
>>but can't return a string array..
what make you thing that?

A variant that is a BSTR needs no conversion.  It already is a string.  Just tell VB that it is an array of Strings and when the C++ module gets them use the _bstr_t(x) extractor.  Or if actually creating the string in the C++ module, then create _variant_t values that have been assigned string data.

Another alternative is to use fixed-width strings.  For instance, in VB,

    Dim HomebrewStringArray as String * 1000

provides a buffer for passing 1000 bytes of data to the COM module.  You can treat that 1000-byte buffer as an array of 10 100-byte strings or as a 2-D array of 5 rows with 2 columns of 100-bytes strings, etc.  You will need to 'roll-yer-own' logic for handling it, but it will be blazing fast.

>>Which seems to me to be negating the speed advantage I
>>have of calling the c++ function in the first place.

If a data conversion is needed (and I'm not certian that it is in this case), and it looks like VB is doing it easily while VC++ requires many steps, then you have just stumbed on the reason that VB is slower -- it does more work for you in a single statement.  For instance, *every* access of a VB variable is an access of a variant data type.  So there are conversions taking place all of the time, without you even noticing.

-- Dan
0
 
LVL 7

Expert Comment

by:peterchen092700
ID: 6838808
>>  a VB component can pass a string array back to another VB appliction using COM
yep, it uses an SafeArray for this

(I think you *can* declare the parameter as SAFEARRAY directly, but this Only avoids the thin VARIANT wrapper)

In the VC++ componentent, it would be wise to keep the strings as BSTR as long as possible to avoid ANSI<->UNICODE conversions. _bstr_t is a nice wrapper class (although far from the power of CString...)


Peter
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 10

Author Comment

by:smegghead
ID: 6839103
I think I might have resolved this, I was setting up the safe array with a VT_VARIANT|VT_BSTR as the base type, which was passing the element values back at Variant/String, which was fine, except that I had to convert ( using cstr(backval(1,0)) ), however, if the base type is declared as just VT_BSTR, and the elements are added as CComBstr.m_str, rather than variants, then it still returns a variant (containing an array), but this can be directly assigned to a VB String() with no conversion.

My problem is solved.

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6839927
Glad to be of service.

-- Dan
0
 
LVL 10

Author Comment

by:smegghead
ID: 6840083
Hi,

Thank you all for your help in this question.

Points go to christophm, as his comment made the most interesting reading.

Smg.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6840996
You can give the points to whomever you want.  I find it a bit odd, though, that you would give the points to christophm when you ended up using none of his suggestions while poor DanRollins told you exactly what to do to solve your problem and when you did it, the problem was solved.  I am just a little bit puzzled.

-- Dan
0
 
LVL 10

Author Comment

by:smegghead
ID: 6841203
Hi Dan,

I was wondering why you said 'Glad to be of service' :-)

None of the comments actually got me to where I wanted, it was just through sheer experimentation.

I read your comment, but it seemed that it was more an explanation of how to pass a String array into c++, whereas I'm trying to do it the other way around.

I'm sorry if my points distribution didn't seem fair. It's very difficult awarding points in a manner that it fair to everybody.

The reason christophm got the points was because his comment filled a little gap in my knowledge.

Regardless... please find a question for DanRollins, for 25 points in the new question area.

PS. Sorry peterchen, you're probably feeling left out now :-)
0
 
LVL 7

Expert Comment

by:peterchen092700
ID: 6842325
it's ok for me ;)
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now