Link to home
Start Free TrialLog in
Avatar of List244
List244

asked on

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.
Avatar of pb_india
pb_india

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
   }

Avatar of List244

ASKER

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.
hmm. i have a working example DLL where a function is called with a string which is declared LPTSTR
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
 
BSTRMyFunc(char *Str1,char *Str2)
{
char *Temp="";
strcpy (Temp,Str1);
strcat (Temp,Str2);
BSTR sUnicode;
sUnicode = SysAllocString(A2W(Temp));
return sUnicode;
}


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,
:)
Avatar of List244

ASKER

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".




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();
}
Avatar of List244

ASKER

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.
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...
Avatar of List244

ASKER

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.)
Avatar of List244

ASKER

CComBSTR is a declare, got it. How about the USES_CONVERSION;?
ASKER CERTIFIED SOLUTION
Avatar of esorf
esorf

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for the points!  - Frank