?
Solved

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

Posted on 2004-09-24
8
Medium Priority
?
457 Views
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,
Curtis
0
Comment
Question by:curtisn
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
8 Comments
 
LVL 19

Expert Comment

by:drichards
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.
0
 

Author Comment

by:curtisn
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.
0
 

Author Comment

by:curtisn
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.

-Curtis
0
Independent Software Vendors: 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!

 
LVL 19

Expert Comment

by:drichards
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.
0
 
LVL 19

Accepted Solution

by:
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.
0
 

Author Comment

by:curtisn
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.

0
 

Expert Comment

by:VoodooAttack
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..
0
 

Author Comment

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

-Curtis
0

Featured Post

Industry Leaders: 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!

Question has a verified solution.

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

In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
The SignAloud Glove is capable of translating American Sign Language signs into text and audio.
Simple Linear Regression
Starting up a Project
Suggested Courses

777 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