Solved

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

Posted on 2004-09-24
8
424 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
base64 decode encode 12 119
move one pixel 4 58
This code tracks birthdays 3 56
How to obtain Administrator permission when you are the Administrator 6 58
Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
A short article about problems I had with the new location API and permissions in Marshmallow
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
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 …

932 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

20 Experts available now in Live!

Get 1:1 Help Now