VB, Callbacks and Strings 
Author Message
 VB, Callbacks and Strings

You can use strlen (a C library function provided in the API) to get the
length of the C-string from the pointer passed to the VB routine.
The you use rtlmovememory to copy the correct number of bytes into a byte
array. last, you use StrConv to convert the byte array into
a B-string (i.e. a VB string).



Quote:
> OK, here's the problem:

> I have a VB application that uses a C/C++ DLL. The DLL provides an
interface
> that is used to pass error messages back to the calling application. This
> mechanism is handled by having the application designate a callback
function
> to the DLL. The error message is a parameter to the callback, and it is a
> C-style string.

> Here is the callback function I am using:

> Sub ErrorMessageHandler(message As String)
> ' some code here. We would like to use the MsgBox function to display the
> message
> End Sub

> So far, I can get the callback registered properly, and it is called
> appropriately by the DLL (now that I have everything worked out as
__stdcall
> functions, etc.). The problem is that the string passed as a parameter
seems
> to be unusable. That is, it's not a Basic string really, and if I try to
> access it, the application hangs.

> Is there any way that I can somehow convert the C-style string into
> something that Basic can use? An array of Byte? This is frustrating
because
> the data is there, but I can't get my mitts on it.

> Thanks in advance...



Tue, 21 May 2002 03:00:00 GMT  
 VB, Callbacks and Strings
VB requires that strings passed to VB callbacks be Unicode BSTR.   Allocate
a word (16-bit char) buffer, pass your LPSTR to MultiByteToWideChar, then
pass the newly filled buffer to SysAllocString.

--
     Jim Mack
     MicroDexterity, Inc
     www.microdexterity.com


Quote:
> OK, here's the problem:

> I have a VB application that uses a C/C++ DLL. The DLL provides an
interface
> that is used to pass error messages back to the calling application. This
> mechanism is handled by having the application designate a callback
function
> to the DLL. The error message is a parameter to the callback, and it is a
> C-style string.

> Here is the callback function I am using:

> Sub ErrorMessageHandler(message As String)
> ' some code here. We would like to use the MsgBox function to display the
> message
> End Sub

> So far, I can get the callback registered properly, and it is called
> appropriately by the DLL (now that I have everything worked out as
__stdcall
> functions, etc.). The problem is that the string passed as a parameter
seems
> to be unusable. That is, it's not a Basic string really, and if I try to
> access it, the application hangs.

> Is there any way that I can somehow convert the C-style string into
> something that Basic can use? An array of Byte? This is frustrating
because
> the data is there, but I can't get my mitts on it.



Wed, 22 May 2002 03:00:00 GMT  
 VB, Callbacks and Strings
Hi Jeff,

VB strings are something called BSTR in COM. When interfacing with DLL's
requiring C style strings (zero terminated) VB _does_ a conversion for you
in both directions.

Another important point. On this style of interfacing VB/C code you have to
declare all your string paremeters as ByVal on th VB side!
This is very important.

The next important point. You should declare callbacks on std modules on VB
side!!!

Right! The C side function has to be declared as __stdcall.

Let's have a look at the following code. It gets the caption of a form using
the GetWindowsText API function.

Private Declare Function GetWindowText lib "user32" Alias "GetWindowTextA"
 _
    ByVal hWnd As Long, _
    ByVal lpString As String, _
    ByVal nMaxCount As Long _
    ) As Long

Sub Form1_Click()
    Const N = 256
    Dim strBuf As String
    strBuf = String(N, Chr(0)) ' create a buffer
    Dim nLen As Long
    nLen = GetWindowText(Me.hWnd, strBuf, Len(strBuf))
    strBuf = Left(strBuf, nLen)
    MsgBox strBuf
End Sub

Before calling GetWindowText VB converts your UNICODE buffer to ANSI and
after returning it converts the result back to UNICODE.

Back to your problem.

C side declaration (test.dll):

typedef void (__stdcall* CALLBACKPROC)(LPCSTR pszText);

CALLBACKPROC* g_pfnCallback = NULL;

void __stdcall setCallback(CALLBACKPROC* pfnCallback)
{
    g_pfnCallback = pfnCallback;

Quote:
}

/* just a stub */
void __stdcall fireEvent(LPCSTR pszText)
{
    if (NULL != g_pfnCallback)
        (*g_pfnCallback)(pszText);

Quote:
}

void __stdcall doTheJob()
{
    fireEvent("Starting...");

    // do some work here
    for (...)
    {
        fireEvent("Work in progress...");
    }

    fireEvent("Done!");

Quote:
}

On VB side (test.bas):

Declare Procedure setCallback Lib "test.dll" (ByVal pfnCallback As Long)
Declare Procedure doTheJob Lib "test.dll"

Public Sub test()
    Call setCallback(AddressOf myCallback)    ' set callback
    Call doTheJob
    Call setCallback(0)    ' remove callback
End Sub

Public Sub myCallback(ByVal s As String)
    Debug.Print s
End Sub

Hope this helps.

IMHO this kind of callbacks are deprecated, we have to use them only when
dealing with legacy code.
The way to go is COM! Even with legacy systems it's better to build COM
wrappers...

Regards,
Peter

Quote:
> OK, here's the problem:

> I have a VB application that uses a C/C++ DLL. The DLL provides an
interface
> that is used to pass error messages back to the calling application. This
> mechanism is handled by having the application designate a callback
function
> to the DLL. The error message is a parameter to the callback, and it is a
> C-style string.

> Here is the callback function I am using:

> Sub ErrorMessageHandler(message As String)
> ' some code here. We would like to use the MsgBox function to display the
> message
> End Sub

> So far, I can get the callback registered properly, and it is called
> appropriately by the DLL (now that I have everything worked out as
__stdcall
> functions, etc.). The problem is that the string passed as a parameter
seems
> to be unusable. That is, it's not a Basic string really, and if I try to
> access it, the application hangs.

> Is there any way that I can somehow convert the C-style string into
> something that Basic can use? An array of Byte? This is frustrating
because
> the data is there, but I can't get my mitts on it.

> Thanks in advance...



Wed, 22 May 2002 03:00:00 GMT  
 VB, Callbacks and Strings
If you control the interface on the C side, would you *really*
use this solution over just fixing up the C side to use a BSTR?

--
MichKa

don't ask by e-mail unless you're paying for it. (TANSTAAFL!) :-)

random junk of dubious value, a multilingual website, the
worldwide TSI Form/Report to Data Access Page Wizard,
and lots of replication "stuff" at http://www.trigeminal.com/


Quote:
> You can use strlen (a C library function provided in the API)
to get the
> length of the C-string from the pointer passed to the VB
routine.
> The you use rtlmovememory to copy the correct number of bytes
into a byte
> array. last, you use StrConv to convert the byte array into
> a B-string (i.e. a VB string).




> > OK, here's the problem:

> > I have a VB application that uses a C/C++ DLL. The DLL
provides an
> interface
> > that is used to pass error messages back to the calling
application. This
> > mechanism is handled by having the application designate a
callback
> function
> > to the DLL. The error message is a parameter to the callback,
and it is a
> > C-style string.

> > Here is the callback function I am using:

> > Sub ErrorMessageHandler(message As String)
> > ' some code here. We would like to use the MsgBox function to
display the
> > message
> > End Sub

> > So far, I can get the callback registered properly, and it is
called
> > appropriately by the DLL (now that I have everything worked
out as
> __stdcall
> > functions, etc.). The problem is that the string passed as a
parameter
> seems
> > to be unusable. That is, it's not a Basic string really, and
if I try to
> > access it, the application hangs.

> > Is there any way that I can somehow convert the C-style
string into
> > something that Basic can use? An array of Byte? This is
frustrating
> because
> > the data is there, but I can't get my mitts on it.

> > Thanks in advance...



Wed, 22 May 2002 03:00:00 GMT  
 VB, Callbacks and Strings
Although I do control the "C" side of things, it's not a matter of merely
"fixing it up". Our DLL is intended to be general purpose, and I don't wish
to add any more functions to our API than necessary. If I can come up with a
way to access the data from the callback from within VB, then that is the
kind of solution I am looking for. If I can't, then I will have to augment
our API. But since I am far from an expert at VB, I didn't know whether such
a thing was even possible in Basic



Quote:
> If you control the interface on the C side, would you *really*
> use this solution over just fixing up the C side to use a BSTR?

> --
> MichKa



> > You can use strlen (a C library function provided in the API) to get the
> > length of the C-string from the pointer passed to the VB routine.
> > The you use rtlmovememory to copy the correct number of bytes into a
byte
> > array. last, you use StrConv to convert the byte array into
>> a B-string (i.e. a VB string).



Fri, 24 May 2002 03:00:00 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. VB Style Strings and Callbacks in C/C++

2. CALLBACK, CALLBACK, CALLBACK?

3. Thread-safe callbacks and VB?

4. ATL And VB Callback

5. Problem with calling VB ActiveX from callback

6. VB callback function, called from a VC DLL, crashes

7. Return values from VB CallBack Function to VC Dll

8. Callback to a VB function

9. Callbacks to VC and VB

10. Providing a callback to VB from VC

11. Providing a callback to VB from VC

12. Passing strings in/out of callbacks

 

 
Powered by phpBB® Forum Software