Results 1 to 9 of 9

Thread: Callback from C dll to VB6

  1. #1

    Thread Starter
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Callback from C dll to VB6

    Has anyone seen a working example of making an asynchronous callback from a C++ dll to VB6?
    The steps are:
    1. Set callback address by sending addressof subroutine to dll
    2. dll stores this value in a global variable for later use
    3. dll launches a seperate thread and returns control to VB
    4. New thread performs some work and makes a callback to VB using the previously set address.

    The problem is with the parameters passed back to VB
    The logic works within the IDE
    If compiled, the callback is made, but if I try to access the parameters passed, it crashes. This tells me there is something wrong with the stack?

    Here is a demo code
    C++
    Code:
    / All declarations which are needed resides in "windows.h"
    #include <windows.h>
    
    // Placeholder for function-export macros
    #define LIBRARY_EXPORT __declspec(dllexport) __stdcall
    
    // Function Declarations for Static Export
    extern "C" {
    long LIBRARY_EXPORT GetDBData(void);
    long LIBRARY_EXPORT SetCallbackProcAddr(long);
    }
    
    // Function Declaration for Callback function of the Calling App
    //typedef void (CALLBACK* TDataReadNotify)(long);
    typedef void (__stdcall *TDataReadNotify)(long);
    
    / Vars for Imported Functions
    TDataReadNotify DataReadNotify;
    HANDLE hThread;
    DWORD pThreadId;
    
    static DWORD DoTheWork(LPVOID lpParameter)
    {
      static long lDBData;
    
    // Doing stuff that takes 5 sec., i.e. reading DB Data.
    
      Sleep(5000);
      lDBData = 123;
    
    // Notify the caller app via CB-function.
      if (DataReadNotify != NULL) DataReadNotify(lDBData);
    
      return 0;
    };
    
    long LIBRARY_EXPORT GetDBData(void)
    {
      long lProcAdr;
    
    // Get ProcAddress for Thread-Func and create/run the thread.
      lProcAdr = (long)(&DoTheWork);
      hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)lProcAdr, NULL, 0, &pThreadId);
    
    // Return to caller app.
      return 0;
    };
    
    long LIBRARY_EXPORT SetCallbackProcAddr(long lProcAddress)
    {
      long Result = 0;
    
    // Set the Proc-Address for the notify-func of the caller app.
      DataReadNotify = (TDataReadNotify)lProcAddress; 
    
      if (DataReadNotify == NULL) return 0;
    
      return 1;
    };

    VB Code:
    1. Option Explicit
    2.  
    3. Private iWait As Long
    4. Private sDBData As String
    5. Private sMessage As String
    6.  
    7. Public Declare Function GetDBData Lib "DLL_Callback.dll" Alias "_GetDBData@0" () As Long
    8. Public Declare Function SetCallbackProcAddr Lib "DLL_Callback.dll" Alias "_SetCallbackProcAddr@4" (ByVal lProcAddress As Long) As Long
    9.  
    10. Sub Main()
    11.  
    12.  
    13.   iWait = 1
    14.  
    15. ' Send Address-Pointer Information to the DLL
    16.   Call SetCallbackProcAddr(AddressOf DataReadNotify)
    17. ' Call the function of the DLL, which reads DB-Info or something else.
    18.   GetDBData
    19.  
    20. ' if the DLL-function is still busy, loop until the DLL notifies via the CALLBACK-function "DataReadNotify()".
    21.   Do While iWait = 1
    22.     DoEvents
    23.   Loop
    24.  
    25.   iWait = iWait
    26.  
    27. End Sub
    28.  
    29. Public Sub DataReadNotify(ByVal lDBData As Long)
    30.   MsgBox "Sample App: " & CStr(lDBData), vbOKOnly + vbInformation
    31.  
    32. ' Set Wait to 0, so that WinMain can go further.
    33.   iWait = 0
    34.  
    35. End Sub

  2. #2
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Callback from C dll to VB6

    I think the problem is the MsgBox call. Since the callback in called through another thread you can't show blocking msgboxes.

  3. #3

    Thread Starter
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Re: Callback from C dll to VB6

    Yes, it is true that the messageBox call is causing an error so this is not a good example to illustrate the problem.

    Suppose I start the program from a form rather than sub main.
    The DataReadNotify sub will run in another thread than the form. I've found that I can set global variables from the DataReadNotify sub and even access text boxes on the form, but certain things cannot be done such as use Hex (i.e. Form1.text1 = Hex(LBDData)).

    How is it that certain API functions can perform callbacks in the same thread as my main program? Is there some way I can execute a function in a running thread from outside the thread?

  4. #4
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Callback from C dll to VB6

    I'm not sure. But for some reason I haven't had problem with many other callback functions. For example I've been able to call up MsgBoxes and such in a TimerProc callback after a SetTimer call. Maybe you could use that... in your callback procedure in VB you simply create a timer with a low interval, just enough for your callback to finish executing and then do the job in the callback procedure for the timer... Just a stupid work-around suggestion.

  5. #5
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Callback from C dll to VB6

    Here's another idea if you're using Forms: Subclass your form and send it a message you've defined yourself each time the callback procedure is called. That way you can use the wParam or lParam arguments to pass on the data without storing them in global variables first.

  6. #6

    Thread Starter
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Re: Callback from C dll to VB6

    Yes, there are many work arounds that I could implement, but shouldn't I be able to build my callback so that it acts like callbacks from APIs? I would just like to know how they do it.
    For example I've been able to call up MsgBoxes and such in a TimerProc callback after a SetTimer call
    This is exactly my point. If I don't have problems with callbacks MS devises why is mine not working?
    in your callback procedure in VB you simply create a timer with a low interval, just enough for your callback to finish executing and then do the job in the callback procedure for the timer.
    I doubt that this would work since if the problem is as I expect that the thread has not been properly initialized, then a callback to an unintialized thread isn't going to work either. I may try it just to confirm my suspicions however. Thanks

  7. #7
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Callback from C dll to VB6

    Quote Originally Posted by moeur
    in your callback procedure in VB you simply create a timer with a low interval, just enough for your callback to finish executing and then do the job in the callback procedure for the timer
    I doubt that this would work since if the problem is as I expect that the thread has not been properly initialized, then a callback to an unintialized thread isn't going to work either. I may try it just to confirm my suspicions however. Thanks
    Maybe you're right! However the subclassing and sending a message to your form approach should work, since it's then sent to the regular thread in the VB process.

  8. #8
    Addicted Member
    Join Date
    Apr 2003
    Posts
    148

    Re: Callback from C dll to VB6

    Code:
      lProcAdr = (long)(&DoTheWork);
    what do if i change DoTheWork to :
    Code:
    LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
    I got Error when i do this
    Code:
      lProcAdr = (long)(GetMsgProc);

  9. #9
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Callback from C dll to VB6

    You need the ampursand before the function name.
    Code:
    lProcAdr = (long)(&GetMsgProc)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width