Solved

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

Posted on 2004-09-24
8
421 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
  • 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
 
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 19

Accepted Solution

by:
drichards earned 500 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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

A short article about a problem I had getting the GPS LocationListener working.
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.
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

744 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now