[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 301
  • Last Modified:

C++ Dll problem.

I am trying to write a C++ function that returns a string to VB.
I would like to do this as a return, rather than send a reference
to C++. I have read a little that says BSTR is the same as the
string for VB. But, I can not get BSTR working...

However, I have already asked a similar question with no
response, so I am going to change it a little. Is BSTR a lot
more difficult than using a reference?

I would like a little information on whichever you feel is the
BEST way to do it. Thanks.
0
List244
Asked:
List244
  • 5
  • 5
  • 3
  • +1
1 Solution
 
pb_indiaCommented:
Using BSTR is not difficult than reference.

Basically, BSTR equals String.
However, in a function declaration:
ByRef <=> BSTR*
ByVal <=> BSTR

BSTR means 'basic string' and is designed to replicate the VB string type
for passing around between VB/VC....this is documented more fully in the
msdn.

To pass the string TO VB, pass it as BSTR *


//Ex. to manipuate string FROM VB

 HRESULT AppendString(BSTR StringFromVB) {
      char *v_lpszCPlusString;
      v_lpszCPlusString = new char[strlen(getMBString(StringFromVB)) + 1];
       strcpy(v_lpszCPlusString,getMBString(StringFromVB));
      //Do what ever you want
   }
if you are passing a variant from VB then

   HRESULT AppendString(VARIANT StringFromVB) {
      char *v_lpszCPlusString;
      v_lpszCPlusString = new char[strlen(getMBString(StringFromVB.bstrVal)) + 1];
       strcpy(v_lpszCPlusString,getMBString(StringFromVB.bstrVal));
      //Do what ever you want
   }

0
 
List244Author Commented:
I am still getting error with BSTR. Basically I need a function like:

char MyFunc(char *Str1,char *Str2)
{
char *Temp;
strcpy (Temp,Str1);
strcat (Temp,Str2);
}

That then returns Temp to VB. So basically a function that
appends two vb strings and returns it.
0
 
Tai-SanCommented:
hmm. i have a working example DLL where a function is called with a string which is declared LPTSTR
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
esorfCommented:
Here's a good reference on type conversions: http://www.codeguru.com/Cpp/Cpp/string/conversions/article.php/c5639/
Here are some samples of BSTR methods: http://support.microsoft.com/kb/196976/EN-US/

Here's a stab at your function (sorry, I didn't try to compile and test it).

BSTR ConcatBstrs(BSTR a, BSTR b)  // passed by value
{
       int alen = SysStringByteLen(a);
       int blen = SysStringByteLen(b);

       BSTR result = SysAllocStringLen(NULL, alen + blen);

       memcpy((char *)result, a, alen);
       memcpy(((char *)result)+alen, b, blen);

       return result;
}

- Frank
0
 
pb_indiaCommented:
 
BSTRMyFunc(char *Str1,char *Str2)
{
char *Temp="";
strcpy (Temp,Str1);
strcat (Temp,Str2);
BSTR sUnicode;
sUnicode = SysAllocString(A2W(Temp));
return sUnicode;
}


0
 
pb_indiaCommented:
u can also use the following:

you can use _bstr_t object as follows:

#include <comdef.h>
....
{
...
    char* s = "Hello";  //Your Temp
    _bstr_t t(s);
    BSTR bs = t.copy();  //Return this bs to VB
....
}

Regards,
:)
0
 
List244Author Commented:
Esorf, yours is the only one that does not error upon
compilation.

India

Function 1 errors with:
A2W - not defined
Return - cant convert short* to int
Return - incosistent return statement

Function 2:
MyDll.Def : error LNK2001: unresolved external symbol Attach - {
Debug/MyDll.lib : fatal error LNK1120: 1 unresolved externals -     BSTRAttach(char *Str1,                                                                                                 char *Str2)
LINK : fatal error LNK1141: failure during build of exports file -                          }

However, Esorf, when I run in VB, I get:

Private Declare Function Attach Lib "Location\MyDll.dll" (String1 As String, String2 As String) As Long

MsgBox Attach("My", " test.")

Error - The instruction at "MEMORY ADDRESS" referenced memory at "MEMORY ADDRESS", the memory could not be "read".




0
 
esorfCommented:
Doh!  I'm a bit rusty with BSTRs

Firstly, your VB declaration needs to be
    Private Declare Function Attach Lib "Location\MyDll.dll" (String1 As String, String2 As String) As String
Notice that the function returns a string, not a Long.

#include <atlbase.h>

And then change the C logic to the following:
{
    //need for conversion macro OLE2T, atlconv.h may need to be included
    USES_CONVERSION;
    CComBSTR bstrOut(a);
    bstrOut.AppendBSTR(b);
    return bstrOut.Detach();
}
0
 
List244Author Commented:
Yeah, I changed to long some time ago for a test, guess
I forgot to switch it back. It is no longer erroring, however
it is giving me bad calling convention. I am passing it the
correct amount of arguments, in string form. Any ideas?
I have increased the points for this question.
0
 
esorfCommented:
Yeah, calling convention has to do with how parameters are put on the stack and who has the responsibility for cleaning them off the stack.  The VB declaration has to match the C implementation.

Your C method should be declared
    extern "C" BSTR __stdcall ConcatBstrs(BSTR a, BSTR b)

Let us know how it goes...
0
 
List244Author Commented:
extern "C" BSTR __stdcall Attach(BSTR a, BSTR b)
{
    //need for conversion macro OLE2T, atlconv.h may need to be included
    USES_CONVERSION;
    CComBSTR bstrOut(a);
    bstrOut.AppendBSTR(b);
    return bstrOut.Detach();
}

Works! thank you.

One last set of questions however.

USES_CONVERSION;
CComBSTR

Can you explain what those are, and why they are necessary?

Also (IF you happen to know) is "C++ for VB programmers"
a good resource for this kind of programming?(If you do not
know about the book, don't worry about that question.)
0
 
List244Author Commented:
CComBSTR is a declare, got it. How about the USES_CONVERSION;?
0
 
esorfCommented:
Yeah, CComBSTR is a handy class that does a lot of BSTR manipulation work so you don't have to.

USES_CONVERSION is a #define macro which expands to some kind of initialization to support multibyte character conversion.  Frankly, I don't know that it is necessary here.  Try removing it.

Some further discussions of USES_CONVERSION and associated risks (because it allocates buffers on the stack) are here:
http://www.experts-exchange.com/Programming/Programming_Languages/Q_20455812.html
http://www.mindcracker.com/mindcracker/c_cafe/atl/cout.asp

Cheers,

- Frank
0
 
esorfCommented:
Thanks for the points!  - Frank
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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