Problem combining a visual basic app, c++ dll, and callback methods

Posted on 2004-09-24
Medium Priority
Last Modified: 2010-04-17
The short of my question is this: How do I create a VB callback that is invoked from within a c++ dll which passes a character string from the c++ dll to the VB callback method.

Specifically, my VB app loads a dll I created in c++.  This dll needs to notify the app of certain events created by the user.  One of these events requires that a character message be sent from the c++ dll to the VB app.  

The pointer to the callback function:
(CALLBACK* AddEntityFunc)(short index, float x, float y, short type, BSTR text);

in C++ the exported function to receive the callback method looks like this.
void __declspec(dllexport) CALLBACK AddEntityFunc(long address)
    AddEntityFunc = (void (CALLBACK*)(short index, float x, float y, short type, BSTR text))address;
in vb the method to callback looks like
Public Sub AddEntityCallback(ByVal index As Integer, ByVal x As Single, ByVal y As Single, ByVal t As Integer, ByVal str As String)

frm.label = str                      'Just to see if we get the correct data.

End Sub

When I invoke the vb callback method I use something like:
short id = 2;
float x = 3.2;
float y = 5.39;
short type = 1;
and data is a previously filled char array of up to 50 characters.
AddEntityFunc(index, x,y,type, data);

I've tried createing an array of unsigned shorts to pass in, but it crashes the program,
I've tried casting the char array to a BSTR, but that crashes the program.
I would prefer not to use MFC as the dll has not been built with MFC.
Can anyone give me some direction on this?  I am stuck.  

Thanks in advance,
Question by:curtisn
  • 4
  • 3
LVL 19

Expert Comment

ID: 12148057
As far as I know, you cannot call directly into VB from C++.  You need to use COM if you want to do that.

Author Comment

ID: 12150698
Actually, you can. I am doing it plenty with my program, I am able to send back single characters, shorts, and longs to VB from c++. even whole parameter lists.  The one part I am struggling with is sending the string at the end.  I imagine there are a few lines to convert a char * to a BSTR, but for the life of me I can't figure it out.  I can send a String from VB to c++.  But not the other way.

Author Comment

ID: 12150714
additionally, sometimes the dll will need to send the empty string.  Clearly I could solve this by writting another callback, but I am interested in solving both of these with the same callback method.

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

LVL 19

Expert Comment

ID: 12150921
>>  I can send a String from VB to c++.  
Yes, but the VB runtime does a bit of magic to make that work.  You'll notice that even though VB uses BSTR's internally, a call out to a function with a char* parameter will succeed.  Once the call has passed the VB boundary, the runtime doesn't case any more.  I assume that the 'Declare' statements produce some kind of marshaling code.  This doesn't exist for the callback on the raw pointer you handed out to the C function.  I'll be curious to see if someone knows the bit of magic to make it work.

It's interesting that you can do a callback from C to VB with basic types, though.  I'll definitely add that to my bag of tricks.
LVL 19

Accepted Solution

drichards earned 2000 total points
ID: 12151824
As I was out biking this morning, I realized it is not surprising that you can call back into the VB once the C/C++ dll is loaded into the VB process.  It is only calling from C/C++ executable into VB that is problematic.  Also, as I reread your initial problem, you say you 'tried casting the char array to a BSTR'.  Do you really mean cast, or did you actually create a BSTR? A BSTR has a 4 bytes length preceding the character pointer, so casting will most definitely crash your program even if the characters are UNICODE which is the other property of a BSTR.

Starting with a char array, you need to do something like:

    wchar_t wideChar[256]; // use appropriate size
    mbstowcs(wideChar, charArray, 256); // charArray is your original string:  char charArray[];
    BSTR myBSTR = SysAllocString(wideChar);

Then you can try passing myBSTR back to VB.  If you already did this, then I do not now what else to try.

Author Comment

ID: 12156594
This sounds like it might work, I will try it when I get to work Monday morning.  Thanks for the better understanding of BSTR, I thought it was simply a pointer to an array of unsigned shorts.  I am very new at the VB end of things, and that is why I am having so much grief.


Expert Comment

ID: 12156638
I guess you should try to pass the string by reference.

In VB:
Public Sub AddEntityCallback(ByVal index As Integer, ByVal x As Single, ByVal y As Single, ByVal t As Integer, ByRef str As String)

In C++:
(well, i'm not very experienced with C)
But you should try to pass the address of the string directly to VB (as a long)..
as long as i know: byval causes troubles with strings (especially in a call back function)

If this doestn't work:
I had similar proplems with this in assembly, and i used to pass strings to visual basic with a trick
try to change the string parameter into two parameters, the first is a long with the address, and the
second is the length of the file, in VB you should use CopyMemory to copy them into a byte array.
Then use strConv to convert the byte array into a unicode String.
One more thing, you should pass the parameter of the CHAR, as is without conversion or any thing.
str = Strconv(StringArray, vbUnicode)

If i can help with anything please reach me at: voodooattack@hotmail.com

Best regards..

Author Comment

ID: 12160944
Thanks, that was exactly the answer I was looking for, it works perfectly now.  I didn't know about the mbstowcs function!


Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
Computer science students often experience many of the same frustrations when going through their engineering courses. This article presents seven tips I found useful when completing a bachelors and masters degree in computing which I believe may he…
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …

809 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