• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 296
  • Last Modified:

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

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
smegghead
Asked:
smegghead
  • 5
  • 3
  • 3
  • +1
1 Solution
 
peterchen092700Commented:
No, not without an safearray.


(Why do you think any other method would be easier?)
0
 
smeggheadAuthor Commented:
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
 
smeggheadAuthor Commented:
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
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
christophmCommented:
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
 
DanRollinsCommented:
>>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
 
peterchen092700Commented:
>>  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
 
smeggheadAuthor Commented:
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
 
DanRollinsCommented:
Glad to be of service.

-- Dan
0
 
smeggheadAuthor Commented:
Hi,

Thank you all for your help in this question.

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

Smg.
0
 
DanRollinsCommented:
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
 
smeggheadAuthor Commented:
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
 
peterchen092700Commented:
it's ok for me ;)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 5
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now